package gbench.common.matlib;

import gbench.common.fs.XlsFile.DataMatrix;
import gbench.common.matlib.img.ImageOps;
import gbench.common.matlib.img.ImagePlot;

import java.awt.image.BufferedImage;
import java.lang.reflect.Array;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoField;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.*;
import java.util.regex.Pattern;
import java.util.stream.*;

import static java.lang.Math.*;

/**
 * 数学家画布 <br>
 * <br>
 * 一个绘图画布就是 通过提供一条轴向采样点序列，<br>
 * 然后不断的进行维度扩增而建构span出一种 图形图像(形状) 的 空间的思维&工具框架。<br>
 * <br>
 * MatlibCanvas 的本质(思想) 是 空间构建器. <br>
 * <br>
 * MatlibCanvas 的关键是它对 绘图的基本概念的设计。<br>
 * MatlibCanvas 的本质就是对 空间的操作。<br>
 * MatlibCanvas 把空间视为维度范围(Range)的结构。每个维度范围是由 (start,end,step) 三元组构成。<br>
 * Range 维度范围 提供出一组方便的 采样点结构 的生成方法(map,dblA,dblS等) 以及 维度范围组织方法(span)。<br>
 * 这样我们构造除了一种 多维空间的 立体采样点 框架。<br>
 * 在这个立体的 采样框架中(采样点空间)，我们可以借助于Range.map 变换出的含有采样点坐标索引信息的数据，
 * 即空间结构概念点Point:每个Point，就被视为 一种 索引键值结构:IVPair 即IVP.<br>
 * 可以通过对 Index 的变换(IVPair.analze) 将数据分理处 坐标索引即空间索引(坐标） 以及 索引值即 空间点内容。
 * 于是对空间的操作就变成了对 IVP的操作。 <br>
 * <br>
 * 为了方便计算我们把IVP做了特化，即索引结构采用int[],即整数列表的方式,即 DataPoint<br>
 * 以方便与cartesian坐标系对应。于是对空间的操作就变成对DataPoint的操作。 <br>
 * 我们采用向量化思想来管理&操作DataPoint结构。为此我们专门设计TVec这种类型化的数组操作结构，
 * 并针对于绘图要求,制作了NVec来作为MatlibCanvas的主要 点数据的操作工具。<br>
 * 这样在NVec的协助下我们就可以 对各种数学概念进行绘图。<br>
 * <br>
 * 对于平面图像图像。我们采用一个5维向量xyrgb [x,y,r,g,b]来表示:<br>
 * 所以一副图片就对应于一个xyrgb的向量列表 实际为一个 稀疏矩阵(Sparse Matrix)。<br>
 * 于是对图片的创建修改与操作就变成了对xyrgb列表/稀疏矩阵的操作。<br>
 * 稀疏矩阵的[xyrgb]使得我们可以采用矩阵的方式来操作xyrgb列表:[xyrgb]，即引入线性代数的概念与方法。<br>
 * 这也是为何我们把绘图操作叫做MatlibCanvas的意思，即每个绘图操作都是可以被视为一种矩阵计算。<br>
 * 借鉴工程软件MATLAB的设计思想,或者说从MATLAB获得了原始的启发&灵感<br>
 * 
 * @author gbench
 */
public class MatlibCanvas {
    
    /**
     * 数学家画布（内置一个Range对象）  <br>
     * param start 像素水平坐标x的开始位置 默认为 0 inclusive <br>
     * param end  像素水平坐标x的结束位置  默认为 500 exclusive
     */
    public MatlibCanvas(){
        
        this(0,500,1);
    }
    
    /**
     * 数学家画布 （内置一个Range对象） <br>
     * param start  像素水平坐标x的开始位置 默认为 0 inclusive <br>
     * @param end   像素水平坐标x的结束位置(像素水平坐标的最大值) exclusive 
     */
    public MatlibCanvas(final Number end){
        
        this(0,end,1);
    }
    
    /**
     * 数学家画布 （内置一个Range对象） <br>
     * @param start  像素水平坐标x的开始位置 inclusive 
     * @param end  像素水平坐标x的结束位置 exclusive
     */
    public MatlibCanvas(final Number start,final Number end){
        
        this(start,end,1);
    }
    
    /**
     * 数学家画布 （内置一个Range对象） <br>
     * @param start 像素水平坐标x的开始位置 inclusive
     * @param end  像素水平坐标x的结束位置 exclusive
     * @param step 步长大小
     */
    public MatlibCanvas(final Number start,final Number end,final Number step){
        
        this.range = new Range(start,end,step);
    }
    
    /**
     * 绘制一条曲线
     * @param fx y值函数
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public Stream<int[]> drawLine(final Function<Double,Double> fx){
        
        return this.drawLine(fx,(Boolean)null);
    }
    
    /**
     * 绘制一条曲线
     * @param fx y值函数
     * @param flipFlag 是否反转坐标轴，flipFlag 是否颠倒 坐标x,y次序
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public Stream<int[]> drawLine(final Function<Double,Double> fx,final Boolean flipFlag){
        
        return this.drawLine(fx, (int[])null,(Boolean)flipFlag);
    }
    
    /**
     * 绘制一条曲线
     * @param fx y值函数
     * @param color 线条颜色
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public Stream<int[]> drawLine(final Function<Double,Double> fx, final int[] color){
        
        return this.drawLine(fx,color,(Boolean)null);
    }
    
    /**
     * 绘制一条曲线
     * @param fx y值函数
     * @param color 线条颜色
     * @param flipFlag 是否反转坐标轴，flipFlag 是否颠倒 坐标x,y次序
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public Stream<int[]> drawLine(final Function<Double,Double> fx, final int[] color, final Boolean flipFlag){
        
        return this.drawLine(null,fx,color,flipFlag);
    }
    
    /**
     * 绘制一条曲线
     * @param range x的变化范围
     * @param fx y值函数
     * @param color 颜色现象
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public Stream<int[]> drawLine(final Range range, final Function<Double,Double> fx, final int[] color){
        
        return this.drawLine(range,fx,color,(Boolean)null);
    }
    
    /**
     * 绘制一条曲线
     * @param range x的变化范围
     * @param fx y值函数
     * @param color 颜色现象
     * @param flipFlag 是否反转坐标轴，flipFlag 是否颠倒 坐标x,y次序
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public Stream<int[]> drawLine(final Range range, final Function<Double,Double> fx, 
        final int[] color, final Boolean flipFlag){
        
        final var clr = (color==null ? this.color : color); // 线条颜色
        final var stream = this.drawLine( range, fx,  (x,y)-> point(x,y,clr,flipFlag) );
        
        return stream.flatMap( continuous_line() );
    }
    
    /**
     * 绘制一条曲线
     * @param start 开始顶点
     * @param end 结束点 exclusive
     * @param fx y值函数
     * @param color 线条颜色
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public Stream<int[]> drawLine(final Number start,final Number end,
        final Function<Double,Double> fx, final int[] color){
        
        return this.drawLine(new Range(start,end), fx, color);
    }

    /**
     * 绘制一条曲线
     * @param <T> 节点序列的元素类型
     * @param fx y值函数
     * @param point_renderer 点向量生成函数:(x,y)->t
     * @return 节点序列:[t]
     */
    public <T> Stream<T> drawLine(final Function<Double,Double> fx,final BiFunction<Double,Double,T> point_renderer){
        
        return this.drawLine(null,fx, point_renderer);
    }
    
    /**
     * 绘制一条曲线
     * <核心函数>
     * @param <T> 节点序列的元素类型
     * @param range x 的变化范围
     * @param fx y值函数
     * @param point_renderer 点向量生成函数:(x,y)->t
     * @return 节点序列:[t]
     */
    public <T> Stream<T> drawLine(final Range range, final Function<Double,Double> fx,
        final BiFunction<Double,Double,T> point_renderer){
        
        final var rng = (range == null ? this.range : range);
        
        return rng.dblStream().map(x -> point_renderer.apply(x, fx.apply(x)));
    }

    /**
     * 绘制一条曲线
     * @param fx y值函数
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public List<int[]> drawLine2(final Function<Double,Double> fx){
        
        return this.drawLine(fx).collect(Collectors.toList());
    }
    
    /**
     * 绘制一条曲线
     * @param fx y值函数
     * @param color 线条颜色
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public List<int[]> drawLine2(final Function<Double,Double> fx,int[] color){
        
        return this.drawLine(fx,color).collect(Collectors.toList());
    }
    
    /**
     * 绘制一条曲线
     * @param fx y值函数
     * @param color 线条颜色
     * @param flipFlag 是否反转坐标轴，flipFlag 是否颠倒 坐标x,y次序
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public List<int[]> drawLine2(final Function<Double,Double> fx,int[] color,Boolean flipFlag){
        
        return this.drawLine2(range,fx,color,flipFlag);
    }
    
    /**
     * 绘制一条曲线
     * @param fx y值函数
     * @param color 线条颜色
     * @param flipFlag 是否反转坐标轴，flipFlag 是否颠倒 坐标x,y次序
     * @return 节点序列:[[x,y,r,g,b]]
     */
    public List<int[]> drawLine2(final Range range,final Function<Double,Double> fx,
        int[] color,Boolean flipFlag){
        
        return this.drawLine(range,fx,color,flipFlag).collect(Collectors.toList());
    }
    
    /**
     * 绘制一条曲线
     * @param <T> 节点序列的元素类型
     * @param fx y值函数
     * @param point_renderer 点向量生成函数:(x,y)->t
     * @return 节点序列:[t]
     */
    public <T> List<T> drawLine2(final Function<Double,Double> fx,
        final BiFunction<Double,Double,T> point_renderer){
        
        return this.drawLine2((Range)null,fx, point_renderer);
    }

    /**
     * 绘制一条曲线
     * @param <T> 节点序列的元素类型
     * @param range x 的变化范围
     * @param fx y值函数
     * @param point_renderer 点向量生成函数:(x,y)->t
     * @return 节点序列:[t]
     */
    public <T> List<T> drawLine2(final Range range,final Function<Double,Double> fx,
        final BiFunction<Double,Double,T> point_renderer){
        
        return this.drawLine(range,fx, point_renderer).collect(Collectors.toList());
    }
    
    /**
     * 绘制一条曲线
     * 核心函数 <br>
     * @param <T> 节点序列的元素类型
     * @param range x 的变化范围
     * @param fx y值函数
     * @param point_renderer 点向量生成函数:(x,y)->t
     * @param indexer 行号 列号 t->{行索引,列索引}
     * @param valueer 值提取 t->u 
     * @return 节点序列:[t]
     */
    public <T,U> U[][] drawLine3(final Range range,final Function<Double,Double> fx,
        final BiFunction<Double,Double,T> point_renderer,
        final Function<T,int[]> indexer,final Function<T,U> valueer){
        
        return matrix(this.drawLine(range,fx, point_renderer).collect(Collectors.toList()),indexer,valueer);
    }
    
    /**
     * 绘制一条曲线
     * 核心函数 <br>
     * @param <T> 节点序列的元素类型
     * @param fx y值函数
     * @param point_renderer 点向量生成函数:(x,y)->t
     * @param indexer 行号 列号 t->{行索引,列索引}
     * @param valueer 值提取 t->u 
     * @return 节点序列:[t]
     */
    public <T,U> U[][] drawLine3(final Function<Double,Double> fx,
        final BiFunction<Double,Double,T> point_renderer,
        final Function<T,int[]> indexer,final Function<T,U>valueer){
        
        return matrix(this.drawLine(fx, point_renderer).collect(Collectors.toList()),
            indexer,valueer);
    }
    
    /**
     * 绘制一条曲线
     * 核心函数 <br>
     * @param fx y值函数
     * @return 节点矩阵 行号是x,列号是y
     */
    public int[][][] drawLine3(final Function<Double,Double> fx){
        
        return matrix(this.drawLine(fx).collect(Collectors.toList()),e->e
            ,e->Arrays.copyOfRange(e, 2, e.length));
    }
    
    /**
     * 点向量
     * 
     * @param x 水平坐标
     * @param y 垂直坐标
     * @return [x,y,r,g,b]
     */
    public int[] point(final Number x,final Number y) {
        
       return point(x,y,null,false);
    }

    /**
     * 点向量
     * 
     * @param x 水平偏移 
     * @param y 垂直偏移
     * @param rgb 色彩数组
     * @return [x,y,r,g,b]
     */
    public int[] point(final Number x,final Number y,final int[]rgb) {
        
        return point(x,y,rgb,null);
    }
    
    /**
     * 点向量
     * 
     * @param x 水平偏移 
     * @param y 垂直偏移
     * @param rgb 色彩数组
     * @param flipFlag 是否调转 索引坐标  x,y位置
     * @return [x,y,r,g,b]
     */
    public int[] point(final Number x,final Number y,final int[]rgb,final Boolean flipFlag) {
        
        final var clr = (rgb==null?this.color:rgb);//色彩向量
        final var p = ( flipFlag==null ? this.flipFlag : flipFlag )
            ? new int[] {y.intValue(),x.intValue(), clr[0],clr[1],clr[2]}
            : new int[] {x.intValue(),y.intValue(), clr[0],clr[1],clr[2]};
            
        return p;
    }
    
    /**
     * 笛卡尔坐标 形式的 点结构  <br>
     * cartesian_point_nvec的别名 <br>
     * 
     * @param f y值的计算函数
     * @return x->NVec 的函数,即一个 [x,f(x),r,g,b]的向量
     */
    public Function<Double,NVec> fx(final Function<Double,Number> f) {
        
        return x->cartesian_point_nvec(x,f.apply(x));
    }
    
    /**
     * 笛卡尔坐标 形式的 点结构  <br>
     * cartesian_point_nvec的别名 <br>
     * 
     * @param point [x水平坐标,y垂直坐标]
     * @return NVec 对象
     */
    public NVec xY(final NVec point){
        
        if(point==null||point.size()<2)return null;
        
        return this.xY(point.get(0),point.get(1));
    }

    /**
     * 笛卡尔坐标 形式的 点结构  <br>
     * cartesian_point_nvec的别名 <br>
     * 
     * @param x 水平坐标
     * @param y 垂直坐标
     * @return NVec 对象
     */
    public NVec xY(final Number x,final Number y) {
        
        return cartesian_point_nvec(x,y);
    }
    
    /**
     * 笛卡尔坐标 形式的 点结构
     * 
     * @param x 水平坐标
     * @param y 垂直坐标
     * @return NVec 对象
     */
    public NVec cartesian_point_nvec(final Number x,final Number y) {
        
       return this.cartesian_point_nvec(x, y, (int[])null, flipFlag);
    }
    
    /**
     * 笛卡尔坐标 形式的 点结构  <br>
     * cartesian_point_nvec的别名 <br>
     * 
     * @param x 水平坐标
     * @param y 垂直坐标
     * @param flipFlag 是否调转 索引坐标  x,y位置
     * @return NVec 对象
     */
    public NVec xY(final Number x,final Number y,final Boolean flipFlag) {
        
        return cartesian_point_nvec(x,y,flipFlag);
    }

    /**
     * 笛卡尔坐标 形式的 点结构  <br>
     * cartesian_point_nvec的别名 <br>
     * 
     * @param x 水平坐标
     * @param y 垂直坐标
     * @param flipFlag 是否调转 索引坐标  x,y位置
     * @return NVec 对象
     */
    public NVec cartesian_point_nvec(final Number x,final Number y,
        final Boolean flipFlag) {
        
        return this.cartesian_point_nvec(x, y, (int[])null, flipFlag);
    }
    
    /**
     * 笛卡尔坐标 形式的 点结构  <br>
     * cartesian_point_nvec的别名 <br>
     * 
     * @param x 水平偏移 
     * @param y 垂直偏移
     * @param rgb 色彩数组
     * @return NVec 对象
     */
    public NVec xY(final Number x, final Number y,final int[]rgb) {
        
        return this.cartesian_point_nvec(x, y, rgb);
    }

    /**
     * 笛卡尔坐标 形式的 点结构
     * 
     * @param x 水平偏移 
     * @param y 垂直偏移
     * @param rgb 色彩数组
     * @return NVec 对象
     */
    public NVec cartesian_point_nvec(final Number x, final Number y,final int[]rgb) {
        
        return this.cartesian_point_nvec(x, y, rgb, null);
    }

    /**
     * 笛卡尔坐标 形式的 点结构  <br>
     * cartesian_point_nvec的别名 <br>
     * 
     * @param x 水平偏移 
     * @param y 垂直偏移
     * @param rgb 色彩数组
     * @param flipFlag 是否调转 索引坐标  x,y位置
     * @return NVec 对象
     */
    public NVec xY(final Number x, final Number y,
        final int[]rgb, final Boolean flipFlag) {
        
        return this.cartesian_point_nvec(x, y, rgb, flipFlag);
    }
    
    /**
     * 笛卡尔坐标 形式的 点结构  <br>
     * cartesian_point_nvec的别名 <br>
     * 
     * @param x 水平偏移 
     * @param y 垂直偏移
     * @param r 红色分量
     * @param g 绿色分量
     * @param b 蓝色分量
     * @param flipFlag 是否调转 索引坐标  x,y位置
     * @return NVec 对象
     */
    public NVec xY(final Number x, final Number y,
        final Number r,final Number g, final Number b, final Boolean flipFlag) {
        
        return this.cartesian_point_nvec(x, y, new int[] {r.intValue(),g.intValue(),b.intValue()}, flipFlag);
    }

    /**
     * 笛卡尔坐标 形式的 点结构 <br>
     * 核心函数 <br>
     * 
     * @param x 水平偏移,x 可以为双精度 
     * @param y 垂直偏移,y 可以为双精度
     * @param rgb 色彩数组
     * @param flipFlag 是否调转 索引坐标  x,y位置,null 表示采用默认的this.flipFlag的翻转设置。
     * @return NVec 对象,NVec向量有一个优越性就是 它可以进行浮点运算,这对于需要进行 坐标变换的于处理的 点来是非常拥有的。
     */
    public NVec cartesian_point_nvec(final Number x, final Number y,
        final int[]rgb, final Boolean flipFlag) {
        
        // 占位符的点值: x,y not available piont, Integer.MAX_VALUE 表示不可用值 NA.
        final var xy_na_point = point ( Integer.MAX_VALUE,
            Integer.MAX_VALUE, rgb ); // xy 不可用的值
        
        // 生成具有 二次运算能力的NVec, 之所以不使用 NVec.of(point)，是为了保持 住 x,y的双精度。
        // 否则 NVec.of(point)会把小数部分去掉的，所谓为了保持精度这里 采用了 NVec.set 的方式设置x,y
        // 根据 flipFlag 的索引翻转状态, 设置 x,y索引为有效值,  
        return  (flipFlag == null?this.flipFlag:flipFlag) 
            ? NVec.of(xy_na_point).idval_set( 0, y, 1, x ) // x,y 调转顺序,翻转状态
            : NVec.of(xy_na_point).idval_set( 0, x, 1, y ); // x,y 标准顺序,不翻转.
    }
    
    /**
     * 生成极坐标点并进行仿射变换的函数(需要提供两组参数,rhotheta,scales)<br>
     * 
     * @param rhotheta_scales [0:rhothea,1:offsets]<br>
     *                        即数组的的0号元素是[0:rho,1:theta],<br>
     *                        即数组的的1号元素是[0:scalex,1:scaley]<br>
     * 
     * @return 仿射变换之后的NVec(笛卡尔坐标系 )
     */
    public NVec rhotheta_affine_scale(final List<NVec> rhotheta_scales) {

        final var rhotheta = rhotheta_scales.get(0);
        final var scales = rhotheta_scales.get(1);

        return this.rhoTheta(rhotheta.get(0), rhotheta.get(1)).affine(scales.get(0), scales.get(1), 0, 0);
    }

    /**
     * 生成极坐标点并进行仿射变换的函数(需要提供两组参数,rhotheta,scales)<br>
     * 
     * @param rhotheta_scales [0:rhothea,1:offsets]<br>
     *                        即数组的的0号元素是[0:rho,1:theta],<br>
     *                        即数组的的1号元素是[0:scalex,1:scaley]<br>
     * 
     * @return 仿射变换之后的NVec(笛卡尔坐标系 )
     */
    public NVec rhotheta_affine_scale(final NVec[] rhotheta_scales) {

        final var rhotheta = rhotheta_scales[0];
        final var scales = rhotheta_scales[1];

        return this.rhoTheta(rhotheta.get(0), rhotheta.get(1)).affine(scales.get(0), scales.get(1), 0, 0);
    }

    /**
    * 生成极坐标点并进行仿射变换的函数(需要提供两组参数,rhotheta,offsets)<br>
    * 
    * @param rhotheta_offsets [0:rhothea,1:offsets]<br>
    * 即列表的的0号元素是[0:rho,1:theta],<br>
    * 即列表的的1号元素是[0:offsetx,1:offsety]<br>
    * 
    * @return 仿射变换之后的NVec(笛卡尔坐标系 )
    */
   public NVec rhotheta_affine_offset(final List<NVec> rhotheta_offsets){
       
       final var rhotheta = rhotheta_offsets.get(0);
       final var offsets = rhotheta_offsets.get(1);
       
       return this.rhoTheta(rhotheta.get(0),rhotheta.get(1)).affine(1, 1,offsets.get(0), offsets.get(1));
   }
   
   /**
    * 生成极坐标点并进行仿射变换的函数(需要提供两组参数,rhotheta,offsets)<br>
    * 
    * @param rhotheta_offsets [0:rhothea,1:offsets]<br>
    * 即数组的的0号元素是[0:rho,1:theta],<br>
    * 即数组的的1号元素是[0:offsetx,1:offsety]<br>
    * 
    * @return 仿射变换之后的NVec(笛卡尔坐标系 )
    */
   public NVec rhotheta_affine_offset(final NVec[] rhotheta_offsets){
       
       final var rhotheta = rhotheta_offsets[0];
       final var offsets = rhotheta_offsets[1];
       
       return this.rhoTheta(rhotheta.get(0),rhotheta.get(1)).affine(1, 1,offsets.get(0), offsets.get(1));
   }
   
    /**
     * 生成极坐标点并进行仿射变换的函数(需要提供两组参数,rhotheta,offsets)<br>
     * 
     * @param rhotheta_scales_offsets [0:rhothea,1:scales,2:offsets]<br>
     *                         即数组的的0号元素是[0:rho,1:theta],<br>
     *                         即数组的的1号元素是[0:scalex,1:scaley]<br>
     *                         即数组的的2号元素是[0:offsetx,1:offsety]<br>
     * 
     * @return 仿射变换之后的NVec(笛卡尔坐标系 )
     */
    public NVec rhotheta_affine(final List<NVec> rhotheta_scales_offsets) {

        final var rhotheta = rhotheta_scales_offsets.get(0);
        final var scales = rhotheta_scales_offsets.get(1);
        final var offsets = rhotheta_scales_offsets.get(2);

        return this.rhoTheta(rhotheta.get(0), rhotheta.get(1)).affine(scales.get(0), scales.get(1), offsets.get(0),
                offsets.get(1));
    }
   
    /**
     * 生成极坐标点并进行仿射变换的函数(需要提供两组参数,rhotheta,offsets)<br>
     * 
     * @param rhotheta_scales_offsets [0:rhothea,1:scales,2:offsets]<br>
     *                         即数组的的0号元素是[0:rho,1:theta],<br>
     *                         即数组的的1号元素是[0:scalex,1:scaley]<br>
     *                         即数组的的2号元素是[0:offsetx,1:offsety]<br>
     * 
     * @return 仿射变换之后的NVec(笛卡尔坐标系 )
     */
    public NVec rhotheta_affine(final NVec[] rhotheta_scales_offsets) {
        final var rhotheta = rhotheta_scales_offsets[0];
        final var scales = rhotheta_scales_offsets[1];
        final var offsets = rhotheta_scales_offsets[2];
        return this.rhoTheta(rhotheta.get(0), rhotheta.get(1)).affine(scales.get(0), scales.get(1), offsets.get(0),
                offsets.get(1));
    }
   
    /**
     * 生成极坐标点并进行仿射变换的函数<br>
     * 
     * @param scalex x方向缩放比例
     * @param scaley y方向缩放比例
     * @param offsetx x方向平移量
     * @param offsety y方向平移量
     * @return theta->NVec的带有仿射变换能力的 函数 。采用 theta幅角弧度，生成一个单位向量，然后 进行 affine变换。结果是一个NVec
     */
    public Function<Double,NVec> rhotheta_affine(Number scalex,Number scaley,Number offsetx,Number offsety){
        
        return theta -> this.rhoTheta(theta).affine(scalex, scaley,offsetx, offsety);
    }
    
    /**
     * 生成极坐标点并进行仿射变换的函数<br>
     * 
     * @param af 反射变换的系数向量：[scalex x方向缩放比例,scaley y方向缩放比例,offsetx x方向平移量,offsety y方向平移量]
     * @return theta->NVec的带有仿射变换能力的 函数 。采用 theta幅角弧度，生成一个单位向量，然后 进行 affine变换。结果是一个NVec
     */
    public Function<Double,NVec> rhotheta_affine(NVec af){
        
        return this.rhotheta_affine(af.get(0), af.get(1), af.get(2), af.get(3));
    }
    
    /**
     * 生成极坐标点并进行仿射变换的函数<br>
     * 
     * @param offsetx x方向平移量
     * @param offsety y方向平移量
     * @return theta->NVec的带有仿射变换能力的 函数 。采用 theta幅角弧度，生成一个单位向量，然后 进行 affine变换。结果是一个NVec
     */
    public Function<Double,NVec> rhotheta_affine_offset(Number offsetx,Number offsety){
        
        return theta -> this.rhoTheta(theta).affine(1, 1,offsetx, offsety);
    }

    /**
     * 生成极坐标点并进行仿射变换的函数<br>
     * 
     * @param scalex x方向缩放比例
     * @param scaley y方向缩放比例
     * @return theta->NVec的带有仿射变换能力的 函数 。采用 theta幅角弧度，生成一个单位向量，然后 进行 affine变换。结果是一个NVec
     */
    public Function<Double,NVec> rhotheta_affine_scale(Number scalex,Number scaley){
        
        return theta -> this.rhoTheta(theta).affine(scalex, scaley,0, 0);
    }

    /**
     * 生成极坐标点并进行仿射变换的函数(需要提供两个坐标参数,rho,theta)<br>
     * 
     * @param scalex x方向缩放
     * @param scaley y方向缩放
     * @return rhotheta->NVec的带有仿射变换能力的 函数 。<br>
     * rhotheta 是一个NVec向量,至少包括两个元素:[rho,theta,...]即0号位置rho,1号位置theta<br>
     * 采用 theta幅角弧度，生成一个单位向量，然后 进行 affine 缩放变换。结果是一个NVec
     */
    public Function<NVec,NVec> rhotheta2_affine_scale(final Number scalex, final Number scaley){
        
        return rhotheta -> this.rhoTheta(rhotheta.get(0),rhotheta.get(1)).affine(scalex, scaley,0, 0);
    }
    
    /**
     * 生成极坐标点并进行仿射变换的函数(需要提供两个坐标参数,rho,theta)<br>
     * 
     * @param offsetx x方向平移量
     * @param offsety y方向平移量
     * @return rhotheta->NVec的带有仿射变换能力的 函数 。<br>
     * rhotheta 是一个NVec向量,至少包括两个元素:[rho,theta,...]即0号位置rho,1号位置theta<br>
     * 采用 theta幅角弧度，生成一个单位向量，然后 进行 affine offset变换。结果是一个NVec
     */
    public Function<NVec,NVec> rhotheta2_affine_offset(final Number offsetx, final Number offsety){
        
        return rhotheta -> this.rhoTheta(rhotheta.get(0),rhotheta.get(1)).affine(1, 1,offsetx, offsety);
    }
    
    /**
     * 生成极坐标点并进行仿射变换的函数<br>
     * 
     * @param scalex x方向缩放比例
     * @param scaley y方向缩放比例
     * @param offsetx x方向平移量
     * @param offsety y方向平移量
     * @return rhotheta->NVec的带有仿射变换能力的 函数 。<br>
     * rhotheta 是一个NVec向量,至少包括两个元素:[rho,theta,...]即0号位置rho,1号位置theta<br>
     * 采用 theta幅角弧度，生成一个单位向量，然后 进行 affine变换。结果是一个NVec
     */
    public Function<NVec,NVec> rhotheta2_affine(Number scalex,Number scaley,Number offsetx,Number offsety){
        
        return rhotheta -> this.rhoTheta(rhotheta.get(0),rhotheta.get(1)).affine(scalex, scaley,offsetx, offsety);
    }
    
    /**
     * 生成极坐标点并进行仿射变换的函数<br>
     * 
     * @param af 反射变换的系数向量：[scalex x方向缩放比例,scaley y方向缩放比例,offsetx x方向平移量,offsety y方向平移量]
     * @return rhotheta->NVec的带有仿射变换能力的 函数 。<br>
     * rhotheta 是一个NVec向量,至少包括两个元素:[rho,theta,...]即0号位置rho,1号位置theta<br>
     * 采用 theta幅角弧度，生成一个单位向量，然后 进行 affine变换。结果是一个NVec
     */
    public Function<NVec,NVec> rhotheta2_affine(final NVec af){
        
        return rhotheta -> this.rhoTheta(rhotheta.get(0),rhotheta.get(1)).affine(af.get(0), af.get(1), af.get(2), af.get(3));
    }

    /**
     * 极坐标 形式点：单位向量 (rho,theta) <br>
     * polar_point_nvec 的别名 <br>
     * rho的长度默认为1
     * 
     * @param theta 方向角度
     * @return NVec 对象
     */
    public NVec rhoTheta(final Number theta) {
        
       return this.polar_point_nvec(null, theta);
    }
    
    /**
     * 极坐标 形式点：单位向量(1,theta)
     * 
     * @param theta 方向角度
     * @return NVec 对象
     */
    public NVec polar_point_nvec(final Number theta) {
        
       return this.polar_point_nvec(null, theta);
    }
    
    /**
     * 极坐标 形式点：单位向量 (rho,theta) <br>
     * polar_point_nvec 的别名 <br>
     * 
     * @param rho   矢径长度, null 默认为1
     * @param theta 方向角度
     * @return NVec 对象
     */
    public NVec rhoTheta(final Number rho, final Number theta) {
        
        return this.polar_point_nvec(rho,theta);
    }
    
    /**
     * 极坐标 形式点：单位向量 (rho,theta) <br>
     * polar_point_nvec 的别名 <br>
     * 
     * @param nvec [0:rho矢径长度,1:theta方向角度]
     * @return NVec 对象
     */
    public NVec rhoTheta(final NVec nvec) {
        
        return this.polar_point_nvec(nvec.get(0),nvec.get(1));
    }

    /**
     * 极坐标 形式点：单位向量 (rho,theta)
     * 
     * 核心函数 <br>
     * 
     * @param rho   矢径长度,null 默认为1
     * @param theta 方向角度
     * @return NVec 对象
     */
    public NVec polar_point_nvec(final Number rho, final Number theta) {
        
        final var final_rho = (rho==null?1:rho.doubleValue());
        final var x = final_rho * Math.cos(theta.doubleValue());
        final var y = final_rho * Math.sin(theta.doubleValue());
        
        return this.cartesian_point_nvec(x, y, null, flipFlag);
    }
    
    /**
     * 极坐标 形式点：单位向量 (rho,theta) <br>
     * polar_point_nvec 的别名 <br>
     * 
     * @param rho   矢径长度, null 默认为1
     * @param theta 方向角度
     * @param rgb   色彩数组
     * @return NVec 对象
     */
    public NVec rhoTheta(final Number rho, final Number theta, final int[] rgb) {
        
        return this.polar_point_nvec(rho, theta, rgb);
    }
    
    /**
     * 极坐标 形式点：单位向量 (rho,theta)
     * 
     * 核心函数 <br>
     * 
     * @param rho   矢径长度,null 默认为1
     * @param theta 方向角度
     * @param rgb 色彩数组
     * @return NVec 对象
     */
    public NVec polar_point_nvec(final Number rho, final Number theta,final int[] rgb) {
        
        final var final_rho = (rho==null?1:rho.doubleValue());
        final var x = final_rho * Math.cos(theta.doubleValue());
        final var y = final_rho * Math.sin(theta.doubleValue());
        
        return this.cartesian_point_nvec(x, y, rgb, flipFlag);
    }
    
    /**
     * 坐标轴反转：翻转 x,y的顺序。 <br>
     * true:第一索引y,第二索引x 即 颜色点向量 [y,x,r,g,b] <br>
     * false:第一索引x,第二索引y 即 颜色点向量 [x,y,r,g,b] <br>
     * @return MatlibCanvas 对象本省便于实现链式编程。
     */
    public MatlibCanvas flip() {
        
        this.flipFlag = !this.flipFlag;
        
        return this;
    }
    
    /**
     * 坐标轴是否被翻转 <br>
     * true:第一索引y,第二索引x 即 颜色点向量 [y,x,r,g,b] <br>
     * false:第一索引x,第二索引y 即 颜色点向量 [x,y,r,g,b] <br>
     * @return 坐标轴的翻转状态
     */
    public Boolean isFlipped(){
        
        return this.flipFlag;
    }

    /**
     * 图像渲染 <br>
     * <br>
     * 本函数不会对图像数据做变换操作。<br>
     * <br>
     * 注意：因为图片的高度坐标从从上向下递增，而我们一般的数学习惯 是 坐标轴是从下向上递增的。<br>
     * 所以采用数学坐标绘制的图像,一般需要上下翻转的变换,即 y=height-y才能给予正确显示<br>
     * 数据点的翻转操作可以 在 renderer 回调函数中给予进行. <br>
     * 
     * @param sessionCallback 会话操作函数
     * @param width           宽度
     * @param height          高度
     * @return BufferedImage
     */
    public BufferedImage drawImage(final int width,final int height,
        final Consumer<PenSession> sessionCallback) {
        
        return this.drawImage(width, height, sessionCallback,data->{});
    }

    /**
     * 图像渲染 <br>
     * 核心函数 <br>
     * <br>
     * 注意：因为图片的高度坐标从从上向下递增，而我们一般的数学习惯 是 坐标轴是从下向上递增的。<br>
     * 所以采用数学坐标绘制的图像,一般需要上下翻转的变换,即 y=height-y才能给予正确显示<br>
     * 数据点的翻转操作可以 在 renderer 回调函数中给予进行 <br>
     * 
     * @param sessionCallback 会话操作函数
     * @param width           宽度
     * @param height          高度
     * @param renderer        数据渲染操作函数：比如做 图像的上下翻转操作: <br>
     *                        data -> data.forEach( e-> e[1] = height-e[1] )
     * @return BufferedImage
     */
    public BufferedImage drawImage(final int width, final int height,
        final Consumer<PenSession> sessionCallback,Consumer<List<int[]>> renderer ) {
        
        return this.drawImage(width, height, sessionCallback, e->{
            renderer.accept(e);
            return e.stream();
        });
    }
    
    /**
     * 图像渲染 :区别在于这里的renderer是一个Function而不是Consumer<br>
     * 核心函数 <br>
     * <br>
     * 注意：因为图片的高度坐标从从上向下递增，而我们一般的数学习惯 是 坐标轴是从下向上递增的。<br>
     * 所以采用数学坐标绘制的图像,一般需要上下翻转的变换,即 y=height-y才能给予正确显示<br>
     * 数据点的翻转操作可以 在 renderer 回调函数中给予进行 <br>
     * 
     * @param sessionCallback 会话操作函数
     * @param width           宽度
     * @param height          高度
     * @param renderer        数据渲染操作函数：比如做 图像的上下翻转操作: <br>
     *                        data -> {data.forEach( e-> e[1] = height-e[1] );reurn
     *                        data;};
     * @return BufferedImage
     */
    public BufferedImage drawImage(final int width, final int height,
        final Consumer<PenSession> sessionCallback,Function<List<int[]>,Stream<int[]>> renderer ) {
        
        return this.drawImage(width, height, sessionCallback, renderer, LinkedList::new);
    }
    
    /**
     * 图像渲染 :区别在于这里的renderer是一个Function而不是Consumer<br>
     * 核心函数 <br>
     * <br>
     * 注意：因为图片的高度坐标从从上向下递增，而我们一般的数学习惯 是 坐标轴是从下向上递增的。<br>
     * 所以采用数学坐标绘制的图像,一般需要上下翻转的变换,即 y=height-y才能给予正确显示<br>
     * 数据点的翻转操作可以 在 renderer 回调函数中给予进行 <br>
     * 
     * @param sessionCallback 会话操作函数
     * @param width           宽度
     * @param height          高度
     * @param renderer        数据渲染操作函数：比如做 图像的上下翻转操作: <br>
     *                        data -> {data.forEach( e-> e[1] = height-e[1] );reurn
     *                        data;};
     * @param xyrgbSupplier        绘图会话session的xyrgb缓存构建器
     * @return BufferedImage
     */
    public BufferedImage drawImage(final int width, final int height,
        final Consumer<PenSession> sessionCallback,Function<List<int[]>,Stream<int[]>> renderer, final Supplier<List<int[]>> xyrgbSupplier) {
        
        final var sess = this.new PenSession(xyrgbSupplier); // 制造一个绘图会话
        sessionCallback.accept(sess);

        final var wd = ImageOps.between(0, width);
        final var ht = ImageOps.between(0, height);
        final var imgdata = renderer.apply(sess.xyrgbs).filter(e -> wd.test(e[0]) && ht.test(e[1])); // 去除无效像素，非法坐标。
        final var image = ImageOps.xyrgbs2bimg(width, height, imgdata);// 制作图片
        sess.reset();// 数据恢复

        return image;
    }
    
    /**
     * 图像渲染<br>
     * 
     * 对图像数据做 纵向翻转 以保证 生成的图片内容在视觉上 符合数学习惯。<br>
     * 
     * @param width           宽度
     * @param height          高度
     * @param sessionCallback 会话操作函数
     * @return BufferedImage 图片数据
     */
    public BufferedImage plot(final int width,final int height,
        final Consumer<PenSession> sessionCallback) {
        
        return this.plot(width, height, sessionCallback, null, true);// 调用ImagePlot
    }
    
    /**
     * 图像渲染<br>
     * 
     * 对图像数据做 纵向翻转 以保证 生成的图片内容在视觉上 符合数学习惯。<br>
     * <br>
     * 注意：因为图片的高度坐标从从上向下递增，而我们一般的数学习惯 是 坐标轴是从下向上递增的。<br>
     * 所以采用数学坐标绘制的图像,一般需要上下翻转的变换,即 y=height-y才能给予正确显示<br>
     * 数据点的翻转操作可以 在 renderer 回调函数中给予进行
     * 
     * @param width           宽度
     * @param height          高度
     * @param sessionCallback 会话操作函数
     * @param plotflag        绘图标志,是否调用ImagePlot进行图片显示
     * @return BufferedImage 图片数据
     */
    public BufferedImage plot(final int width,final int height,
        final Consumer<PenSession> sessionCallback, final boolean plotflag) {
        
        return plot(width,height,sessionCallback,null,plotflag);
    }
    
    /**
     * 图像渲染 <br>
     * <br>
     * 注意：因为图片的高度坐标从从上向下递增，而我们一般的数学习惯 是 坐标轴是从下向上递增的。<br>
     * 所以采用数学坐标绘制的图像,一般需要上下翻转的变换,即 y=height-y才能给予正确显示<br>
     * 数据点的翻转操作可以 在 renderer 回调函数中给予进行 <br>
     * 
     * @param width           宽度
     * @param height          高度
     * @param sessionCallback 会话操作函数
     * @param renderer        绘图数据渲染器 <br>
     *                        图像数据为 [[x,y,r,g,b]]->[[x,y,r,g,b]], 可以 在renderer 对像素点进行调整。 <br>
     *                        当renderer 为null, 默认对 图像数据做纵向翻转操作。<br>
     *                        data.stream().peek(e->e[1]=height-e[1]);// 上下对调
     * @param plotflag        绘图标志,是否调用ImagePlot进行图片显示
     * @return BufferedImage 图片数据
     */
    public BufferedImage plot(final int width,final int height,
        final Consumer<PenSession> sessionCallback, 
        final Function<List<int[]>,Stream<int[]>> renderer,
        final boolean plotflag) {
        
        return this.plot(width, height, sessionCallback, renderer, plotflag, img->{});
    }
    
    /**
     * 图像渲染 <br>
     * <br>
     * 注意：因为图片的高度坐标从从上向下递增，而我们一般的数学习惯 是 坐标轴是从下向上递增的。<br>
     * 所以采用数学坐标绘制的图像,一般需要上下翻转的变换,即 y=height-y才能给予正确显示<br>
     * 数据点的翻转操作可以 在 renderer 回调函数中给予进行 <br>
     * 
     * @param width           宽度
     * @param height          高度
     * @param sessionCallback 会话操作函数
     * @param renderer        绘图数据渲染器 <br>
     *                        图像数据为 [[x,y,r,g,b]]->[[x,y,r,g,b]], 可以 在renderer
     *                        对像素点进行调整。 <br>
     *                        当renderer 为null, 默认对 图像数据做纵向翻转操作。<br>
     *                        data.stream().peek(e->e[1]=height-e[1]);// 上下对调
     * @param plotflag        绘图标志,是否调用ImagePlot进行图片显示
     * @param callback        绘图数据调整回调,BufferedImage->{}
     * @return BufferedImage 图片数据
     */
    public BufferedImage plot(final int width,final int height,
        final Consumer<PenSession> sessionCallback, 
        final Function<List<int[]>,Stream<int[]>> renderer,
        final boolean plotflag,Consumer<BufferedImage> callback) {
        
        return this.plot(width, height, sessionCallback, renderer, plotflag, callback, LinkedList::new);
    }
    
    /**
     * 图像渲染 <br>
     * <br>
     * 注意：因为图片的高度坐标从从上向下递增，而我们一般的数学习惯 是 坐标轴是从下向上递增的。<br>
     * 所以采用数学坐标绘制的图像,一般需要上下翻转的变换,即 y=height-y才能给予正确显示<br>
     * 数据点的翻转操作可以 在 renderer 回调函数中给予进行 <br>
     * 
     * @param width           宽度
     * @param height          高度
     * @param sessionCallback 会话操作函数
     * @param renderer        绘图数据渲染器 <br>
     *                        图像数据为 [[x,y,r,g,b]]->[[x,y,r,g,b]], 可以 在renderer
     *                        对像素点进行调整。 <br>
     *                        当renderer 为null, 默认对 图像数据做纵向翻转操作。<br>
     *                        data.stream().peek(e->e[1]=height-e[1]);// 上下对调
     * @param plotflag        绘图标志,是否调用ImagePlot进行图片显示
     * @param callback        绘图数据调整回调,BufferedImage->{}
     * @param xyrgbSupplier        绘图会话session的xyrgb缓存构建器
     * @return BufferedImage 图片数据
     */
    public BufferedImage plot(final int width, final int height, final Consumer<PenSession> sessionCallback,
            final Function<List<int[]>, Stream<int[]>> renderer, final boolean plotflag,
            Consumer<BufferedImage> callback, final Supplier<List<int[]>> xyrgbSupplier) {

        final Function<List<int[]>, Stream<int[]>> final_renderer = renderer != null ? renderer : data -> { // 图像高度数据坐标旋转
            return data.stream().peek(e -> e[1] = height - e[1]);// 上下对调
        }; // 图像渲染器
        final var bufferedImage = this.drawImage(width, height, sessionCallback, final_renderer, xyrgbSupplier); // drawImage
        if (plotflag) {
            if (callback != null) callback.accept(bufferedImage);// 绘图前的图片调整
            ImagePlot.plot(bufferedImage); // 使用 plotflag 控制是否 采用GUI进行绘图
        } // if plotflag

        return bufferedImage;
    }
    
    /**
     * 绘制一条直线 <br>
     * @param x0 开始点  x
     * @param y0 开始点  y
     * @param x1 终止点  x
     * @param y1 终止点  y
     * @return 节点序列:[t]
     */
    public List<int[]> drawStraightLine(int x0, int y0, int x1, int y1,
        final int[] color,final Boolean flipFlag){
        
        return this.drawStraightLine(x0, y0, x1, y1, 
            (x,y)-> point(x,y,color,flipFlag));
    }
    
    /**
     * 绘制一条直线
     * @param <T> 节点序列的元素类型
     * @param range x 的变化范围
     * @param fx y值函数
     * @param point_renderer 点向量生成函数:(x,y)->t
     * @return 节点序列:[t]
     */
    public <T> List<T> drawStraightLine(final Range range, 
        final Function<Double,Double> fx,
        final BiFunction<Double,Double,T> point_renderer) {
        
        final var rng = (range == null ? this.range : range);
        final var aa = rng.startEndS()
            .map(e -> new int[] { e.intValue(), fx.apply(e).intValue() })
            .toArray(int[][]::new);
        
        return this.drawStraightLine(aa[0][0], aa[0][1], 
            aa[1][0], aa[1][1], point_renderer);
    }
    
    /**
     * 绘制一条直线
     * 
     * @param fx y值函数
     * @return 节点序列:[t]
     */
    public List<int[]> drawStraightLine(final Function<Double, Double> fx) {

        return this.drawStraightLine(range, fx, color, flipFlag);
    }

    /**
     * 绘制一条直线
     * 
     * @param range    x 的变化范围
     * @param fx       y值函数
     * @param color    线条颜色
     * @param flipFlag x,y的翻转标记:true,表示翻转
     * @return 节点序列:[t]
     */
    public List<int[]> drawStraightLine(final Range range, 
        final Function<Double, Double> fx, final int[] color,
        final Boolean flipFlag) {

        return this.drawStraightLine(range, fx, (x, y) -> point(x, y, color, flipFlag));
    }
    
    /**
     * 绘制一条直线 <br>
     * 核心函数 <br>
     * 
     * @param <T>            节点序列的元素类型
     * @param x0             开始点 x
     * @param y0             开始点 y
     * @param x1             终止点 x
     * @param y1             终止点 y
     * @param point_renderer 点向量生成函数:(x,y)->t
     * @return 节点序列:[t]
     */
    public <T> List<T> drawStraightLine(int x0, int y0, int x1, int y1,
        final BiFunction<Double, Double, T> point_renderer) {

        final var points = new LinkedList<T>(); // 返回
        bresenham_line(x0, y0, x1, y1, (x, y) -> 
            points.add(point_renderer.apply(x.doubleValue(), y.doubleValue())));

        return points;
    }

    /**
     * 获取主区间范围(自变量:定义域)
     * 
     * @return the range
     */
    public Range getRange() {
        
        return range;
    }

    /**
     * 设置主区间范围(自变量:定义域)
     * 
     * @param range the range to set
     * @return MatlibCanvas 以便于实现链式编程
     */
    public MatlibCanvas setRange(final Range range) {
        
        this.globalStack.push(this.range);// 保存以前的range
        this.range = range;
        
        return this;
    }

    /**
     * 设置主区间范围
     * 
     * @param start 开始位置
     * @param end 结束位置
     * @return MatlibCanvas 以便于实现链式编程
     */
    public MatlibCanvas setRange(final Number start,final Number end) {
        
        this.setRange(new Range(start,end));
        
        return this;
    }

    /**
     * 从堆栈中弹出 最近一次所保存range并将它设置为主区间范围,即 区间范围的回退 <br>
     * 
     * @return MatlibCanvas 以便于实现链式编程
     */
    public MatlibCanvas popRange() {
        
        if(!this.globalStack.empty(Range.class)) {
            this.setRange(this.globalStack.pop(Range.class));
        }//if
        
        return this;
    }

    /**
     * 获取绘图画布的默认画笔色Color
     * @return the color
     */
    public int[] getColor() {
        
        return color;
    }

    /**
     * 设置绘图画布的默认画笔色Color
     * @param color the color to set
     * @return MatlibCanvas 以便于实现链式编程
     */
    public MatlibCanvas setColor(int[] color) {
        
        this.globalStack.push(this.color);
        this.color = color;
        
        return this;
    }
    
    /**
     * 设置绘图画布的默认画笔色Color
     * @param color RGB 颜色，16进制的颜色表示,例如 #ff0000表示红色
     * @return MatlibCanvas 以便于实现链式编程
     */
    public MatlibCanvas setColor(final String color) {
        
        return this.setColor(ImageOps.rgb(color));
    }

    /**
     *  从堆栈中弹出 最近一次所保存Color并将它设置为主区间范围,即 绘图画布的默认画笔色Color 的回退 <br>
     *  
     * @return MatlibCanvas 以便于实现链式编程
     */
    public MatlibCanvas popColor() {
        
        if(!this.globalStack.empty(int[].class)) {
            this.setColor(this.globalStack.pop(int[].class));
        }//if
        
        return this;
    }

    /**
     * 画布重置,即 重设画布为出厂状态，<br>
     * 清空全局堆栈(保存状态过程信息 如 默认绘图色 Color,主区间范围 Range[自变量定义域] 等 的设置 已便于处理  必要的 回退请求 的数据结构) <br>
     * 所以reset只收不做绘图状态回退操作的。<br>
     *  
     * @return MatlibCanvas 以便于实现链式编程
     */
    public MatlibCanvas reset() {
        
        globalStack.reset(Range.class, 
            s->{while(!s.empty())MatlibCanvas.this.setRange(s.pop());});
        globalStack.reset(int[].class, 
            s->{while(!s.empty())MatlibCanvas.this.setColor(s.pop());});
        
        // 清空全局堆栈 
        globalStack.clear();
        
        return this;
    }
    
    /**
     * 绘图会话对象。
     * 一个绘图过程所必要的数据&工具环境<br>
     * 
     * @author gbench
     */
    public class PenSession {
        
        /**
         * 绘图会话构造函数
         */
        public PenSession(){
            
            this(LinkedList::new);
        }
        
        /**
         * 绘图会话构造函数
         * @param xyrgbSupplier xyrgb点向量的数据缓存构造器
         */
        public PenSession(final Supplier<List<int[]>> xyrgbSupplier){
            
            this.xyrgbs = xyrgbSupplier == null ? new LinkedList<>() : xyrgbSupplier.get(); // 构建xyrgb点向量的数据缓存构造器
        }
        
        /**
         * 绘制一条曲线
         * 
         * @param fxs 曲线族函数
         * @return PenSession 便于实现链式编程
         */
        @SafeVarargs
        final public PenSession drawLines(final Function<Double, Double> ... fxs) {
            
            return this.drawLines((Range)null, fxs);
        }
        
        /**
         * 绘制一条曲线
         * 
         * @param start 开始位置 inclusive
         * @param end 结束位置   exclusive
         * @param fxs 曲线族函数
         * @return PenSession 便于实现链式编程
         */
        @SafeVarargs
        final public PenSession drawLines(final Number start,final Number end,
            final Function<Double, Double> ... fxs) {
            
            final var range = new Range(start,end);
            this.drawLines(range, fxs);
            
            return this;
        }
        
        /**
         * 绘制一条曲线 <br>
         * 核心函数 <br>
         * 
         * @param range x的区间范围
         * @param fxs 曲线族函数
         * @return PenSession 便于实现链式编程
         */
        @SafeVarargs
        final public PenSession drawLines(final Range range,
            final Function<Double, Double> ... fxs) {
            
            Arrays.stream(fxs).forEach(fx->this.drawLine(range,fx));
            
            return this;
        }
        
        /**
         * 绘制一条曲线,drawLineX的别名
         * 
         * @param fx y值函数
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Function<Double, Double> fx) {
            
            return this.drawLineX(fx);
        }
        
        /**
         * 绘制一条曲线:
         * 
         * @param fx y值函数
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLineX(final Function<Double, Double> fx) {
            
            return this.drawLine((Range)null,fx,(int[])null,false);
        }
        
        /**
         * 反函数/反转绘制<br>
         * 绘制一条曲线:反转绘制, 按照 即反函数的方式进行绘制
         * 
         * @param fy x值函数
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLineY(final Function<Double, Double> fy) {
            
            return this.drawLine((Range)null,fy,(int[])null,true);
        }
        
        /**
         * 绘制一条曲线
         * 
         * @param range x的区间范围
         * @param fx y值函数
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Range range,
            final Function<Double, Double> fx) {
            
            return this.drawLine(range,fx,null,null);
        }
        
        /**
         * 绘制一条曲线
         * 
         * @param start 开始位置 inclusive
         * @param end 结束位置   exclusive
         * @param fx y值函数
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Number start,final Number end,
            final Function<Double, Double> fx) {
            
            return this.drawLine(start,end,fx,(int[])null);
        }
        
        /**
         * 绘制一条曲线
         * 
         * @param fx y值函数
         * @param color rgb颜色
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Function<Double, Double> fx,
            final int[] color) {
            
            return this.drawLine(null,fx,color,(Boolean)null);
        }
        
        /**
         * 绘制一条曲线
         * 
         * @param start 开始位置 inclusive
         * @param end 结束位置   exclusive
         * @param fx y值函数
         * @param color rgb颜色
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Number start,final Number end,
            final Function<Double, Double> fx,final int[] color) {
            
            return this.drawLine(new Range(start,end),fx,color,(Boolean)null);
        }
        
        /**
         * 绘制一条曲线
         * 
         * @param fx y值函数
         * @param flipFlag 是否反转坐标轴，flipFlag 是否颠倒 坐标x,y次序
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Function<Double, Double> fx,
            final Boolean flipFlag) {
           
            return this.drawLine((Range)null,fx,(int[])null,flipFlag);
        }
        
        /**
         * 绘制一条曲线
         * @param range x的区间范围
         * @param fx y值函数
         * @param flipFlag 是否反转坐标轴，flipFlag 是否颠倒 坐标x,y次序
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Range range,
            final Function<Double, Double> fx,final Boolean flipFlag) {
            
            return this.drawLine(range,fx,null,flipFlag);
        }
        
        /**
         * 绘制一条曲线
         * 
         * @param range x的区间范围
         * @param fx y值函数
         * @param color rgb曲线颜色
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Range range,
            final Function<Double, Double> fx, final int[] color) {
            
            return this.drawLine(range,fx,color,(Boolean)null);
        }

        /**
         * 绘制一组点，并插值成一条连续的线 <br>
         * 点集列表插值<br>
         *
         * @param points 点集列表 ,每个点的 向量式 数格式为 : [x,y,r,g,b],点元素的类型为 NVec结构
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final List<NVec> points) {

            return this.drawLine(points.stream());
        }

        /**
         * 绘制一组点，并插值成一条连续的线 <br>
         * 点集流插值<br>
         *
         * @param points 点集流 ,每个点的 向量式 数格式为 : [x,y,r,g,b],点元素的类型为 NVec结构
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Stream<NVec> points) {

            return this.drawPoints(points.flatMap(MatlibCanvas.nvec_continuous_line2()));
        }

        /**
         * 绘制一组点，并插值成一条连续的线 <br>
         * 点集列表插值<br>
         *
         * @param points 点集列表 ,每个点的 向量式 数格式为 : [x,y,r,g,b],点元素的类型为 NVec结构
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine2(final List<int[]> points) {

            return this.drawLine2(points.stream());
        }

        /**
         * 绘制一组点，并插值成一条连续的线 <br>
         * 点集流插值<br>
         *
         * @param points 点集流 ,每个点的 向量式 数格式为 : [x,y,r,g,b],点元素的类型为 NVec结构
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine2(final Stream<int[]> points) {

            return this.drawPoints2(points.flatMap(MatlibCanvas.continuous_line()));
        }
        
        /**
         * 绘制一条曲线,drawLineX的别名
         * 
         * @param fx y值函数
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final Function<Double,Double> fx) {
            
            this.drawStraightLine(null, fx, null, null);
            
            return this;
        }

        /**
         * 绘制一条曲线,drawLineX的别名
         * 
         * @param range x 的变化范围
         * @param fx y值函数 
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final Range range,
            final Function<Double,Double> fx) {
            
            this.drawStraightLine(range, fx, null, null);
            
            return this;
        }
        
        /**
         * 绘制一条曲线,drawLineX的别名
         *
         * @param fx y值函数
         * @param color 颜色 
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final Function<Double,Double> fx,
            final int []color) {
            
            this.drawStraightLine(null, fx, color, null);
            
            return this;
        }

        /**
         * 绘制一条曲线,drawLineX的别名
         * 
         * @param range x 的变化范围
         * @param fx y值函数
         * @param color 线条颜色 
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final Range range,
            final Function<Double,Double> fx, final int[] color) {
            
            this.drawStraightLine(range, fx, color, null);
            
            return this;
        }
        
        /**
         * 绘制折线,采用节点序列结构[p0:NVec,...,pi,...,pn:NVec]
         * 
         * @param points 直线的起始点 [p0:开始点, p1:中间点, ..., pi:中间点, ..., pn:结束点] 收尾相连的 节点序列
         *               <br>
         *               p0 [x0 开始点 x,y0 开始点 y] <br>
         *               p1 [x1 中间点 x,y1 中间点 y] <br>
         *               ... <br>
         *               pi [xi 中间点 x,yi 中间点 y] <br>
         *               ... <br>
         *               pn [xn 终止点 x,yn 终止点 y] <br>
         *               [p0,p1], [p1,p2], ... ,[pi-1,pi+1], ... ,[pn-1,pn+1]
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final NVec[] points) {
            if(points==null) return this;
            
            var p0 = points[0];// 前一节点
            final var n = points.length;
            for (int i = 1; i < n; i++) {
                final var p1 = points[i];// 获取当前节点
                this.drawStraightLine(p0.i4(0), p0.i4(1), p1.i4(0), p1.i4(1), color, flipFlag);
                p0 = p1;// 跟新前一几点
            }

            return this;
        }
        
        /**
         * 绘制折线,采用节点序列结构[p0:NVec,...,pi,...,pn:NVec]
         * 
         * @param points 直线的起始点 [p0:开始点, p1:中间点, ..., pi:中间点, ..., pn:结束点] 收尾相连的 节点序列
         *               <br>
         *               p0 [x0 开始点 x,y0 开始点 y] <br>
         *               p1 [x1 中间点 x,y1 中间点 y] <br>
         *               ... <br>
         *               pi [xi 中间点 x,yi 中间点 y] <br>
         *               ... <br>
         *               pn [xn 终止点 x,yn 终止点 y] <br>
         *               [p0,p1], [p1,p2], ... ,[pi-1,pi+1], ... ,[pn-1,pn+1]
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final List<NVec> points) {
            if (points == null) return this;
            return this.drawStraightLine(points.toArray(NVec[]::new));
        }
        
        /**
         * 绘制折线,采用节点序列结构[p0:NVec,...,pi,...,pn:NVec]
         * 
         * @param points 直线的起始点 [p0:开始点, p1:中间点, ..., pi:中间点, ..., pn:结束点] 收尾相连的 节点序列
         *               <br>
         *               p0 [x0 开始点 x,y0 开始点 y] <br>
         *               p1 [x1 中间点 x,y1 中间点 y] <br>
         *               ... <br>
         *               pi [xi 中间点 x,yi 中间点 y] <br>
         *               ... <br>
         *               pn [xn 终止点 x,yn 终止点 y] <br>
         *               [p0,p1], [p1,p2], ... ,[pi-1,pi+1], ... ,[pn-1,pn+1]
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final Seq<NVec> points) {
            if (points == null) return this;
            return this.drawStraightLine(points.toArray());
        }

        /**
         * 绘制一条直线
         * 
         * @param x0 开始点  x
         * @param y0 开始点  y
         * @param x1 终止点  x
         * @param y1 终止点  y
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final int x0, final int y0, 
            final int x1, final int y1) {
            
            return this.drawStraightLine(x0, y0, x1, y1, color, flipFlag);
        }
        
        /**
         * 绘制一条曲线,drawLineX的别名 <br>
         * 
         * @param x0 开始点  x
         * @param y0 开始点  y
         * @param x1 终止点  x
         * @param y1 终止点  y
         * @param color 颜色
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final int x0, final int y0, 
            final int x1, final int y1, final int[] color) {
            
            return this.drawStraightLine(x0, y0, x1, y1, color, flipFlag);
        }
        
        /**
         * 绘制一条曲线,drawLineX的别名 <br>
         * 核心函数 <br>
         * @param x0 开始点  x
         * @param y0 开始点  y
         * @param x1 终止点  x
         * @param y1 终止点  y
         * @param color 线条颜色
         * @param flipFlag x,y的翻转标记:true,表示翻转 
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final int x0, final int y0, 
            final int x1, final int y1, int[] color,Boolean flipFlag) {
            
            this.xyrgbs.addAll(MatlibCanvas.this
                .drawStraightLine(x0,y0,x1,y1, color, flipFlag));
            
            return this;
        }
        
        /**
         * 绘制一个点 <br>
         * 
         * @param x 水平坐标
         * @param y 垂直坐标
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoint(final Number x,final Number y) {
            
            return this.drawPoints(()-> Collections.singletonList(MatlibCanvas.this.point(x, y)));
        }
        
        /**
         * 绘制一个点 <br>
         * 
         * @param point 点向量 [x,y,r,g,b]
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoint(final NVec point) {
            
            return this.drawPoints(()-> Collections.singletonList(point.ints()));
        }
        
        /**
         * 绘制一个点 <br>
         * 
         * @param point 点向量 [x,y,r,g,b]
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoint(final int[] point) {
            
            return this.drawPoints(()-> Collections.singletonList(point));
        }
        
        /**
         * 绘制一组点 <br>
         * 点集列表<br>
         * 
         * @param points 点集生成函数,每个点的 向量式 数格式为 : [x,y,r,g,b]
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoints(final Supplier<List<int[]>> points) {
            
            return this.drawPoints(points.get());
        }
        
        /**
         * 绘制一组点 <br>
         * 
         * @param points 点集流 ,每个点的 向量式 数格式为 : [x,y,r,g,b],点元素的类型为 NVec结构
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoints(final Stream<NVec> points) {
            
            return this.drawPoints(points.map(NVec::ints).collect(Collectors.toList()));
        }
        
        /**
         * 绘制一组点 <br>
         * 点集流<br>
         * 
         * @param points 点集流 ,每个点的 向量式 数格式为 : [x,y,r,g,b],点元素的类型为 NVec结构
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoints2(final Stream<int[]> points) {
            
            return this.drawPoints(points.collect(Collectors.toList()));
        }
        
        /**
         * 绘制一组点 <br>
         * 点集流,,带有点集变换功能<br>
         * 
         * @param points 点集流 ,每个点的 向量式 数格式为 : [x,y,r,g,b],点元素的类型为 NVec结构
         * @param transformer 点集的变换函数 [nvec]->[nvec],5 x n
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoints(final Stream<NVec> points,
            final Function<DataMatrix<Double>,DataMatrix<Double>> transformer) {
                
            return this.drawPoints(transformer.apply(Seq.matrix_columns(points)).colS()
                    .map(NVec::new).map(NVec::ints)
                    .collect(Collectors.toList()));
        }
        
        /**
         * 绘制一些列点
         * @param points 点集合, 点是  NVec结构向量
         * @param transformer 点变换 函数 
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoints2(final Stream<NVec> points,
            final Function<Stream<NVec>,List<int[]>> transformer) {
                
            return this.drawPoints(transformer.apply(points));
        }
        
        /**
         * 绘制一些列点
         * @param <T> 预处理器的 结果类型
         * @param points 点集合, 点是  NVec结构向量
         * @param preprocessor 预处理器的 结果类型
         * @param transformer 点变换 函数 
         * @return PenSession 便于实现链式编程
         */
        public <T> PenSession drawPoints2(final Stream<NVec> points,final Function<Stream<NVec>,T> preprocessor,
            final Function<T,List<int[]>> transformer) {
                
            return this.drawPoints(transformer.apply(preprocessor.apply(points)));
        }
        
        /**
         * 绘制一组点 <br>
         * 点集流,带有点集变换功能<br>
         * 
         * @param fx 曲线绘制函数 x->f(x)
         * @param transformer 点集的变换函数 [nvec]->[nvec]
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Function<Double, Double> fx,
            final Function<DataMatrix<Double>,DataMatrix<Double>> transformer) {
        
            final var px = Seq.matrix_columns(MatlibCanvas.this.drawLine(fx).map(NVec::new));// 原始数据
            //System.out.println(px);
            
            final var tx = transformer.apply(px); // 变换后的数据
            //System.out.println(tx);
            
            return this.drawPoints(tx.colS().map(NVec::new).map(NVec::ints)
                .collect(Collectors.toList()));
        }
        
        /***************************************************
         * 
         * 核心函数区域
         * 
         ***************************************************/
        
        /**
         * 绘制一条曲线 <br>
         * 核心函数 <br>
         * 
         * @param range x的区间范围
         * @param fx y值函数
         * @param color rgb曲线颜色
         * @param flipFlag 是否反转坐标轴，flipFlag 是否颠倒 坐标x,y次序
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawLine(final Range range,final Function<Double, Double> fx, 
            final int[] color, final Boolean flipFlag) {
            
            this.xyrgbs.addAll(MatlibCanvas.this.drawLine2(range,fx,color,flipFlag));
            
            return this;
        }
        
        /**
         * 绘制一条曲线,drawLineX的别名 <br>
         * 核心函数 <br>
         * @param range x 的变化范围
         * @param fx y值函数
         * @param color 线条颜色
         * @param flipFlag x,y的翻转标记:true,表示翻转 
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawStraightLine(final Range range,
            final Function<Double,Double> fx, final int[] color, final Boolean flipFlag) {
            
            this.xyrgbs.addAll(MatlibCanvas.this
                .drawStraightLine(range, fx, color, flipFlag));
            
            return this;
        }
        
        /**
         * 绘制一组点 <br>
         * 核心函数<br>
         * 
         * @param points 点集, 每个点的 向量式 数格式为 : [x,y,r,g,b]
         * @return PenSession 便于实现链式编程
         */
        public PenSession drawPoints(final List<int[]> points) {
            
            this.xyrgbs.addAll(points);
            
            return this;
        }
        
        /**
         * 打印显示输出
         * @param flag 是否在err上输出
         * @return xyrgbs
         */
        public List<int[]> dump(final boolean flag) {
            
            if (flag) {
                this.xyrgbs.forEach(e -> System.err.println(ImageOps.box2list(e)));
            }
            
            return this.xyrgbs;
        }
        
        /**
         * 设置区间
         * @param start inclusive
         * @param end exclusive
         * @return PenSession
         */
        public PenSession setRange(final Number start, final Number end) {
            
            return this.setRange(new Range(start,end));
        }
        
        /**
         * 设置区间
         * @param range 绘图范围区间
         * @return PenSession
         */
        public PenSession setRange(final Range range) {
            
            stack.push( MatlibCanvas.this.getRange());
            MatlibCanvas.this.setRange(range);
            
            return this;
        }
        
        /**
         * 恢复区间
         * @return PenSession
         */
        public PenSession resetRange() {
            
            if(stack.empty(Range.class)) {
                System.err.println("range stack is empty");
            }else {
                MatlibCanvas.this.setRange(stack.pop(Range.class));
            }
            
            return this;
        }
        
        /**
         * 设置前景颜色
         * 
         * @param r 红色
         * @param g 绿色
         * @param b 蓝色
         * @return PenSession
         */
        public PenSession setColor(final int r, final int g, final int b) {
            
            return this.setColor(new int[] {r%256,g%256,b%256});
        }

        /**
         * 设置绘图前景颜色
         * @param color 画笔颜色
         * @return PenSession
         */
        public PenSession setColor(final int[] color) {
            
            stack.push(MatlibCanvas.this.getColor());
            MatlibCanvas.this.setColor(color);
            
            return this;
        }
        
        /**
         * 设置绘图前景颜色
         * @param color RGB 颜色，16进制的颜色表示,例如 #ff0000表示红色
         * @return PenSession
         */
        public PenSession setColor(final String color) {
            
           return this.setColor(ImageOps.rgb(color));
        }
        
        /**
         * 恢复绘图前景颜色
         * @return PenSession
         */
        public PenSession resetColor() {
            
            if(stack.empty(int[].class)) {
                System.err.println("color stack is empty");
            }else {
                MatlibCanvas.this.setColor(stack.pop(int[].class));
            }
            
            return this;
        }
        
        /**
         * MatlibCanvas 当前的画布对象
         * @return MatlibCanvas
         */
        public MatlibCanvas getCanvas() {
            
            return MatlibCanvas.this;
        }

        /**
         * 打印显示输出
         * @return 点集合
         */
        public List<int[]> dump() {
            
            return dump(true);
        }
        
        /**
         * 会话清空
         */
        public void reset() {
            
            stack.reset(Range.class, 
                s->{while(!s.empty())MatlibCanvas.this.setRange(s.pop());});
            stack.reset(int[].class, 
                s->{while(!s.empty())MatlibCanvas.this.setColor(s.pop());});
            stack.clear();
            xyrgbs.clear();
        }
        
        /**
         * 缓存中的数据渲染 <br>
         * 比如做好一些坐标变换的操作。
         * @return PenSession
         */
        public PenSession render(Consumer<List<int[]>> renderer) {
            
            renderer.accept(this.xyrgbs);
            
            return this;
        }
        
        private final List<int[]> xyrgbs; // 点向量的数据缓存
        private final MultipleStack stack = new MultipleStack(); // 回退stack;
        
    }
    
    /**
     * 这是一个多类型的堆栈。<br>
     * 
     * @author gbench
     */
    public static class MultipleStack {

        /**
         * 堆栈数据检查
         * 
         * @param obj 压入堆栈的元素
         * @return MultipleStack 本身 以保证 链式编程
         */
        public MultipleStack push(final Object obj) {

            if (obj == null) return this;
            final var cls = obj.getClass();
            final var stack = (Stack<Object>) stacks.computeIfAbsent(cls, e -> new Stack<>());
            stack.push(obj);

            return this;
        }

        /**
         * 弹出堆栈元素
         */
        public <T> T pop(final Class<T> clazz) {

            final var stack = this.getStack(clazz);
            if (stack == null)
                return null;

            return stack.pop();
        }

        /**
         * 堆栈空状态检查
         * 
         * @param <T>   数据原路类型
         * @param clazz 数据元素占位符
         * @return 判断堆栈clazz是否为空
         */
        public <T> boolean empty(final Class<T> clazz) {

            if (this.getStack(clazz) == null)
                return true;

            return this.getStack(clazz).empty();
        }

        /**
         * 数据 重置
         * 
         * @param <T>   数据重置
         * @param clazz 堆栈的元素类型
         * @param cs    回调函数
         * @return MultipleStack 本身 以保证 链式编程
         */
        public <T> MultipleStack reset(final Class<T> clazz, final Consumer<Stack<T>> cs) {

            final var stack = this.getStack(clazz);

            if (stack != null) {
                cs.accept(stack);
            } else {
                if (MatlibCanvas.debug)
                    System.err.println(clazz.getSimpleName() + " 的堆栈数据为空");
            } // if

            return this;
        }

        /**
         * 获取指定类型的堆栈
         * 
         * @param <T>   堆栈元素的类型
         * @param clazz 堆栈的元素类型
         * @return 堆栈
         */
        @SuppressWarnings("unchecked")
        public <T> Stack<T> getStack(final Class<T> clazz) {

            return (Stack<T>) this.stacks.get(clazz);
        }

        /**
         * 清空整个堆栈
         * 
         * @return MultipleStack 本身 以保证 链式编程
         */
        public MultipleStack clear() {

            stacks.clear();

            return this;
        }

        private final Map<Class<?>, Stack<Object>> stacks = new HashMap<>(); // 堆栈集合
    }

    /**
     * 模式匹配：PatternCase 代表了一组模式识别记录 Pattern Entry (模式谓词 predicate,模式行为 action)
     *
     * @param <T> 对象类型
     * @param <V> 值类型
     */
    public static class PatternCase<T, V> {
        /**
         * 模式对象
         *
         * @param instance 原始对象
         */
        public PatternCase(final T instance, final V defaultValue) {
            this.instance = instance;
            this.defaultValue = defaultValue;
            this.patternEntries = new ArrayList<>();
        }

        /**
         * 模式对象
         *
         * @param instance 原始对象
         */
        public PatternCase(final T instance, final V defaultValue,
                           final Collection<IVPair<Predicate<T>, Function<T, V>, ?>> patternEntries) {
            this.instance = instance;
            this.defaultValue = defaultValue;
            this.patternEntries = new ArrayList<>(patternEntries);
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param predicate 模式识别谓词 : t->boolean
         * @param action    模式行为 : t->v
         * @return Case对象本身
         */
        public PatternCase<T, V> when(final Predicate<T> predicate, final Function<T, V> action) {
            patternEntries.add(IVPair.OF(predicate, action));
            return this;
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param <X>       谓词参数类型
         * @param predicate 模式识别谓词 : t->boolean
         * @param action    模式行为 : t->v
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> caseof(final Predicate<X> predicate, final Function<X, V> action) {
            return when(o -> predicate.test((X) o), o -> action.apply((X) o));
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param <X>       谓词参数类型
         * @param predicate 模式识别谓词 : t->boolean
         * @param value     模式行为 , 常量行为 any->value
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> caseof(final Predicate<X> predicate, final V value) {
            return when(o -> predicate.test((X) o), o -> value);
        }

        /**
         * PatternCase对象
         *
         * @param <X>   谓词action参数类型
         * @param clazz  类型占位符,模式识别的类型常量模式
         * @param action 模式行为 : t->v
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> typeof(final Class<X> clazz, final Function<X, V> action) {
            return when(o -> o != null && clazz.isAssignableFrom(o.getClass()),
                    x -> action.apply((X) x));
        }

        /**
         * PatternCase对象
         *
         * @param <X>   谓词action参数类型
         * @param typeholder 类型占位符 模式识别的类型常量模式
         * @param action     模式行为 : t->v
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> typeof2(X typeholder, final Function<X, V> action) {
            final Class<X> clazz = (typeholder == null)
                    ? (Class<X>) Object.class
                    : (Class<X>) typeholder.getClass();
            return typeof(clazz, action);
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param <X>        谓词参数类型
         * @param obj   模式识别谓词 : 当前值:instance equals obj ， 当 obj为 null 时候 谓词为 false
         * @param action    模式行为 : t->v
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> eq(final Object obj, final Function<X, V> action) {
            return when(o -> obj != null && obj.equals(o), o->action.apply((X)o));
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param obj   模式识别谓词 : 当前值:instance equals obj ， 当 obj为 null 时候 谓词为 false
         * @param value 模式行为 , 常量行为 any->value
         * @return Case对象本身
         */
        public PatternCase<T, V> eq(final Object obj, final V value) {
            return when(o -> obj != null && obj.equals(o), o -> value);
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param <X>   谓词action参数类型
         * @param num    模式识别谓词 : 当前值:instance > num ， 当 num 为 null 时候 谓词为 false
         * @param action 模式行为 : t->v
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> gt(final Number num, final Function<X, V> action) {
            return when(o -> num != null && num.doubleValue() <= ((Number) o).doubleValue(),
                    o->action.apply((X)o));
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param obj   模式识别谓词 : 当前值:instance > num ， 当 num 为 null 时候 谓词为 false
         * @param value 模式行为 , 常量行为 any->value
         * @return Case对象本身
         */
        public PatternCase<T, V> gt(final Number obj, final V value) {
            return when(o -> obj != null && obj.doubleValue() <= ((Number) o).doubleValue(),
                    o -> value);
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param <X>    谓词action参数类型
         * @param num    模式识别谓词 : 当前值:instance >= num ， 当 num 为 null 时候 谓词为 false
         * @param action 模式行为 : t->v
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> gte(final Number num, final Function<X, V> action) {
            return when(o -> num != null && num.doubleValue() < ((Number) o).doubleValue(),
                    o -> action.apply((X) o));
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param num   模式识别谓词 : 当前值:instance >= num  ， 当 num 为 null 时候 谓词为 false
         * @param value 模式行为 , 常量行为 any->value
         * @return Case对象本身
         */
        public <X> PatternCase<T, V> gte(final Number num, final V value) {
            return when(o -> num != null && num.doubleValue() < ((Number) o).doubleValue(),
                    o -> value);
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param <X>    谓词action参数类型
         * @param num    模式识别谓词 : 当前值:instance < num  ， 当 num 为 null 时候 谓词为 false
         * @param action 模式行为 , 常量行为 x->value
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> lt(final Number num, final Function<X, V> action) {
            return when(o -> num != null && num.doubleValue() >= ((Number) o).doubleValue(),
                    o -> action.apply((X) o));
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param num   模式识别谓词 : 当前值:instance < num  ， 当 num 为 null 时候 谓词为 false
         * @param value 模式行为 , 常量行为 any->value
         * @return Case对象本身
         */
        public PatternCase<T, V> lt(final Number num, final V value) {
            return when(o -> num != null && num.doubleValue() >= ((Number) o).doubleValue(),
                    o -> value);
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param <X>    谓词action参数类型
         * @param num    模式识别谓词 : 当前值:instance <= num  ， 当 num 为 null 时候 谓词为 false
         * @param action 模式行为 , 常量行为 x->value
         * @return Case对象本身
         */
        @SuppressWarnings("unchecked")
        public <X> PatternCase<T, V> lte(final Number num, final Function<X, V> action) {
            return when(o -> num != null && num.doubleValue() > ((Number) o).doubleValue(),
                    o -> action.apply((X) o));
        }

        /**
         * PatternCase对象 （增加一条模式识别记录）
         *
         * @param num   模式识别谓词 : 当前值:instance <= num  ， 当 num 为 null 时候 谓词为 false
         * @param value 模式行为 , 常量行为 any->value
         * @return Case对象本身
         */
        public PatternCase<T, V> lte(final Number num, final V value) {
            return when(o -> num != null && num.doubleValue() > ((Number) o).doubleValue(),
                    o -> value);
        }

        /**
         * PatternCase对象 (把patternEntries 的模式识别记录添加到当前的 模式识别库中 ）
         * 
         * @param <X>    谓词action参数类型
         * @param patternEntries 模式集合
         * @return Case对象本身
         */
        public <X> PatternCase<T, V> addAll(final Collection<IVPair<Predicate<T>, Function<T, V>, ?>> patternEntries) {
            this.patternEntries.addAll(patternEntries);
            return this;
        }

        /**
         * PatternCase对象 (把 patternCase 的模式识别记录添加到当前的 模式识别库中 ）
         *
         * @param patternCase 模式集合
         * @return Case对象本身
         */
        public <X> PatternCase<T, V> merge(final PatternCase<T,V> patternCase) {
            return this.addAll(patternCase.patternEntries);
        }

        /**
         * 模式计算
         *
         * @param instance 计算实例
         * @return 模式匹配的结果
         */
        public V eval(final T instance) {
            final var final_instance = instance==null ? this.instance : instance;
            return patternEntries.stream()
                    .map(entry -> entry.map1(predicate -> new IVPair<>(predicate.test(final_instance),entry.value())))
                    .filter(IVPair::key)
                    .findFirst().map(e -> e.value().apply(final_instance))
                    .orElse(this.defaultValue);
        }

        /**
         * 模式计算
         *
         * @return 模式匹配的结果
         */
        public V eval() {
            return this.eval(null);
        }

        /**
         * 绑定计算实例
         *
         * @param instance 实例对象
         * @return PatternCase对象
         */
        public PatternCase<T, V> attach(final T instance) {
            this.instance = instance;
            return this;
        }

        /**
         * 复制一个 PatternCase对象
         *
         * @return PatternCase对象
         */
        public PatternCase<T, V> duplicate() {
            return new PatternCase<>(this.instance, this.defaultValue, this.patternEntries);
        }

        /**
         * 把case转对象转换成一个条件函数,相当于:x -> this.eval(x);
         *
         * @return 函数 t->v
         */
        public Function<T, V> fn() {
            return this::eval;
        }

        /**
         * 模式条目的流
         * @return 模式条目的流
         */
        public Stream<IVPair<Predicate<T>, Function<T, V>, ?>> stream(){
            return this.patternEntries.stream();
        }

        /**
         * 格式化输出<br>
         * 输出计算值，相当于 this.eval()+""
         *
         * @return 输出计算值
         */
        public String toString() {
            return this.eval() + "";
        }

        /**
         * T类型的模式识别
         *
         * @param instance 对象实例
         * @param <T>      对象实例类型
         * @param <V>      值类型
         * @return PatternCase对象
         */
        public static <T, V> PatternCase<T, V> defaultcase(final T instance, final V defaultValue) {
            return new PatternCase<>(instance, defaultValue);
        }

        /**
         * X 类型的模式识别
         *
         * @param <X>          某个数据类型
         * @param <V>          数值类型
         * @param defaultValue 默认值
         * @return PatternCase对象
         */
        public static <X,V> PatternCase<X, V> nullcase(final V defaultValue) {
            return new PatternCase<>((X)null, defaultValue);
        }

        private T instance; // 测试对象
        private final V defaultValue; // 默认值
        private final Collection<IVPair<Predicate<T>, Function<T, V>, ?>> patternEntries;
    }
    
    /**
     * 索引键 与 索引值 <br>
     * 这是一个多维度的键值结构(KVPair)<br>
     * 
     * @author gbench
     *
     * @param <K>    索引键的类型
     * @param <V>    值类型的类型
     * @param <SELF> 本身类型：当前类的实际类型，这是一种泛型化实现的向前兼容的设计（技巧）
     */
    public static class IVPair<K, V, SELF> implements Comparable<SELF> {
        
        /**
         * 数据点
         * 
         * @param index 索引，vlaue 的坐标维度
         * @param value 值
         */
        public IVPair(final K index, final V value) {

            this._1 = index;
            this._2 = value;
        }

        /**
         * 索引键
         * 
         * @return 索引键
         */
        public K index() {
        
            return this._1;
        }

        /**
         * 索引值
         * 
         * @return 索引值
         */
        public V value() {
        
            return this._2;
        }
        
        /**
         * 第一位置值:键
         * 
         * @return 第一位置值
         */
        public K key() {
            return this._1;
        }

        /**
         * 第一位置值
         * 
         * @return 第一位置值
         */
        public K _1() {
            return this._1;
        }

        /**
         * 第二位置值
         * 
         * @return 第二位置值
         */
        public V _2() {
            return this._2;
        }

        /**
         * 获取 索引键 的类型类
         * 
         * @return 索引键 的类型类
         */
        @SuppressWarnings("unchecked")
        public Class<K> class1() {
        
            if (this.index() == null)
                return null;
        
            return (Class<K>) this._1.getClass();
        }

        /**
         * 获取 值 的类型类
         * 
         * @return 值 的类型类
         */
        @SuppressWarnings("unchecked")
        public Class<V> class2() {
        
            if (this.value() == null)
                return null;
        
            return (Class<V>) this._2.getClass();
        }

        /**
         * 返回当前对象本身。这是泛型，向前兼容的设计实现。
         * 
         * @return 返回当前对象本身 即 this
         */
        @SuppressWarnings("unchecked")
        public SELF self() {
        
            return (SELF) this;
        }

        /**
         * @param index the index to set
         * @return 返回当前对象本身便于实现链式编程
         */
        public SELF setIndex(final K index) {
        
            this._1 = index;
        
            return this.self();
        }

        /**
         * @param value the value to set
         * @return 返回当前对象本身便于实现链式编程
         */
        public SELF setValue(final V value) {
        
            this._2 = value;
        
            return this.self();
        }

        /**
         * 构造一个克隆体 （ 细菌分裂)
         * 
         * @param k 索引，vlaue 的坐标维度
         * @param v 值
         * @return 构造一个克隆体
         */
        @SuppressWarnings("unchecked")
        public SELF duplicate(final K k,final V v) {
            SELF clone = null;
            try {
                final var ctor = this.getClass().getConstructor(this.class1(),this.class2());
                clone = (SELF)ctor.newInstance(k,v);
            } catch (Exception e) {
                e.printStackTrace();
            }
            
            return clone;
        }
        
        /**
         * 构造一个克隆体 （ 细菌分裂)
         * 
         * @return 构造一个克隆体
         */
        public SELF duplicate() {
            
            return this.duplicate(this._1,this._2);
        }

        /**
         * 结构变换<br>
         * 质变函数 变换:(self)->u<br>
         * 核心函数
         * 
         * @param <U>     目标类型
         * @param mutator 变换函数 self->u
         * @return U 类型的结果
         */
        public <U> U mutate(final Function<SELF, U> mutator) {
            
            return mutator.apply(this.self());
        }

        /**
         * 结构变换<br>
         * 质变函数 变换:(index,value)->u<br>
         * 核心函数
         * 
         * @param <U>     结果值的类型
         * @param mutator 变换器 (index,value)->u
         * @return U 结果类型
         */
        public <U> U mutate(final BiFunction<K, V, U> mutator) {

            return mutator.apply(this._1, this._2);
        }

        /**
         * 通过一个 二元回调函数 对 集合对象采用 根据index进行赋值 <br>
         * 用法示例:<br>
         * V[] vv = ... // vv 是一个数组对象 <br>
         * ivp.assignTo((k,v)->vv[k]=v); <br>
         * <br>
         * 
         * @param assign 被回调的函数
         * @return 返回当前对象本身便于实现链式编程
         */
        public SELF assignTo(final BiConsumer<K, V> assign) {

            assign.accept(index(), value());

            return this.self();
        }

        /**
         * 应用函数技术
         * 
         * @param <U>       结果类型
         * @param evaluator 索引键值计算器:(index,value)->u
         * @return U 类型的结果
         */
        public <U> U evaluate(final BiFunction<K, V, U> evaluator) {

            return evaluator.apply(index(), value());
        }

        /**
         * 递延计算 函数
         * 
         * @param <U>       结果类型
         * @param evaluator 索引键值计算器
         * @return 一个U值的 supplier
         */
        public <U> Supplier<U> lazyEval(final BiFunction<K, V, U> evaluator) {

            return () -> evaluator.apply(this._1, this._2);
        }

        /**
         * 值 映射:v->u
         * 
         * @param <U>    结果值的类型
         * @param mapper 值 映射 函数v->u
         * @return U 结果类型
         */
        public <U> U map(final Function<V, U> mapper) {

            return this.map2(mapper);
        }
        
        /**
         * 映射:(index,value)->u, mutate的别名函数
         * 
         * @param <U>    结果值的类型
         * @param mapper 映射器 v->u
         * @return U 结果类型
         */
        public <U> U map(final BiFunction<K, V, U> mapper) {

            return this.mutate(mapper);
        }
        
        /**
         * 索引 映射:v->u
         * 
         * @param <U>    结果值的类型
         * @param mapper 索引 映射 函数k->u
         * @return U 结果类型
         */
        public <U> U map1(final Function<K, U> mapper) {
        
            return mapper.apply(this.index());
        }

        /**
         * 值 映射:v->u
         * 
         * @param <U>    结果值的类型
         * @param mapper 值 映射 函数v->u
         * @return U 结果类型
         */
        public <U> U map2(final Function<V, U> mapper) {
        
            return mapper.apply(this.value());
        }
        
        /**
         * 比较方法的实现
         */
        @SuppressWarnings("unchecked") @Override
        public int compareTo(final Object p) {
            
            if (p == null) return 1;
            if(!(p instanceof IVPair) ) return -1;
            
            final var comparable = (IVPair<K,V,SELF>)p;
            
            if (this._1() == null && comparable._1() != null) return -1;
            else if (this._1() == null && comparable._1() == null) return 0;
            else if (this._1() != null && comparable._1() == null) return 1;
            else {
                int ret = 0;
                try {
                    ret = ((Comparable<K>)this._1()).compareTo(comparable._1());
                }catch(Exception e) {
                    e.printStackTrace();
                }
                return ret;
            }// if
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T>    元素类型 各个键值得共同基类型
         * @param <U>    结果类型
         * @param mapper 元素变换器，把对象类型Object强制转换成T类型 <br>
         *               而后再把t给予映射成U的函数: t -> u
         * @return T 类型的流 [t]
         */
        @SuppressWarnings("unchecked")
        public <T, U> Stream<U> flattenS(final Function<T, U> mapper) {
            return Stream.of(this.key(), this.value()).filter(Objects::nonNull).flatMap(e -> {
                if (e instanceof IVPair) {
                    return ((IVPair<Object, Object, Object>) e).flattenS(x -> (T) x);
                } else {
                    return Stream.of((T) e);
                } // if
            }).map(mapper);
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         *
         * @param <T> 元素类型 各个键值得共同基类型
         * @param <U> patternCase 模式匹配器
         * @return T 类型的流 [t]
         */
        public <T, U> Stream<U> flattenS(final PatternCase<T, U> patternCase) {
            return this.flattenS(patternCase.fn());
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T>    元素类型 各个键值得共同基类型
         * @param <U>    结果类型
         * @param umapper 元素变换器，T类型元素的函数: t -> u
         * @return U 类型的结果
         */
        public <T,U> U flatten(final Function<T[], U> umapper) {
            return this.flatten(umapper, (Function<Object,T>) null);
        }
        
        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T>     元素类型 各个键值得共同基类型
         * @param <U>     结果类型
         * @param umapper 结果变换函数,[t] ->U 把T类型数组转换成结果类型的函数
         * @param obj2t   结果元素类型变换函数 obj->t
         * @return U 类型的结果
         */
        @SuppressWarnings("unchecked")
        public <T, U> U flatten(final Function<T[], U> umapper, final Function<Object, T> obj2t) {
            final var o2t = obj2t == null ? (Function<Object, T>) (o) -> (T) o : obj2t;
            return umapper.apply(this.flattenS(o2t).collect(Range.aaclc(e -> e)));
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         *
         * @param <T>         元素类型 各个键值得共同基类型
         * @param <U>         结果类型
         * @param mapper      mapper 结果变换函数,[t] ->U 把T类型数组转换成结果类型的函数
         * @param patternCase 模式匹配对象
         * @return U 类型的结果
         */
        public <T, U> U flatten(final Function<T[], U> umapper, final PatternCase<Object, T> patternCase) {
            return this.flatten(umapper, patternCase.fn());
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T>       元素类型
         * @param <R>       结果类型
         * @param collector t 类型的元素归集器 [t] -> R
         * @return R 类型的结果
         */
        public <T, R> R flatten(final Collector<T, ?, R> collector) {
            return this.flatten(collector, null);
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T>       元素类型
         * @param <R>       结果类型
         * @param obj2t     obj2t 结果元素类型变换函数 obj->t
         * @param collector t 类型的元素归集器 [t] -> R
         * @return R 类型的结果
         */
        @SuppressWarnings("unchecked")
        public <T, R> R flatten(final Collector<T, ?, R> collector, final Function<Object, T> obj2t) {
            final var o2t = obj2t == null ? (Function<Object, T>) (o) -> (T) o : obj2t;
            return this.flattenS(o2t).collect(collector);
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T> 结果的元素类型
         * @param obj2t 结果元素类型变换函数 obj->t
         * @return 对象数组
         */
        @SuppressWarnings("unchecked")
        public <T> T[] flattenA(final Function<Object, T> obj2t) {
            final var o2t = obj2t == null ? (Function<Object, T>) (o) -> (T) o : obj2t;
            return this.flatten(e -> (T[]) e, o2t);
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T> 结果的元素类型
         * 
         * @return 对象数组
         */
        @SuppressWarnings("unchecked")
        public <T> T[] flattenA() {
            return this.flattenA(e -> (T) e);
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T> 结果的元素类型
         * @param obj2t 结果元素类型变换函数 obj->t
         * @return 对象数组
         */
        public <T> List<T> flattenL(final Function<Object, T> obj2t) {
            return Arrays.asList(this.flattenA(obj2t));
        }

        /**
         * 把 键值对儿 数据 给予扁平化,主要是对 嵌套IVP类型的数据给予展开<br>
         * 比如 (1,(2,3)) 给予 展开成 [1,2,3] 这样的 流对象<br>
         * 
         * @param <T> 结果的元素类型
         * @return 对象数组
         */
        public <T> List<T> flattenL() {
            return this.flattenL(null);
        }
        
        /**
         * 把键值对儿转换成T类型数据的流
         * 
         * @param <T>          流元素类型
         * @param defaultValue 类型转换失败时候的默认值
         * @return [_1,_2]
         */
        @SuppressWarnings("unchecked")
        public <T> Stream<T> toStream(final T defaultValue) {
            return Stream.of(this._1, this._2).map(e -> {
                if (e != null && defaultValue != null) {
                    return (e.getClass().isAssignableFrom(defaultValue.getClass())) ? (T) e : defaultValue;
                } else if (e != null) {
                    return (T) e;
                } else {
                    return null;
                }
            });
        }

        /**
         * 把键值对儿转换成数组
         * 
         * @param <T>    数组元素类型
         * @param tclazz 元素类型
         * @return [_1,_2]
         */
        @SuppressWarnings("unchecked")
        public <T> T[] toArray(final Class<T> tclazz) {
            T[] tt = null;
            try {
                tt = (T[]) Array.newInstance(tclazz == null ? Object.class : tclazz, 2);
                tt[0] = (T) this._1;
                tt[1] = (T) this._2;
            } catch (Exception e) {
                e.printStackTrace();
            }

            return tt;
        }

        /**
         * 把键值对儿转换成数组
         * 
         * @return 对象数组 [_1,_2]
         */
        public Object[] toArray() {
            return this.toArray(null);
        }
        
        /**
         * 把键值对儿转换成列表
         * 
         * @param <T>          列表元素类型
         * @param defaultValue 类型转换失败时候的默认值
         * @return [_1,_2]
         */
        public <T> List<T> toList(final T defaultValue) {
            return this.toStream(defaultValue).collect(Collectors.toList());
        }

        /**
         * 把键值对儿转换成列表
         * 
         * @return [_1,_2]
         */
        public List<Object> toList() {
           return this.toList(null);
        }
        
        /**
         * 把键值对儿转换成XVec向量
         * @param mapper 数据类型转换 o->u
         * @return XVec向量 [_1,_2]
         */
        public <U> XVec<U> toXVec(final Function<Object,U> mapper) {
            return XVec.OF(this.toArray(null)).fmap(mapper);
        }

        /**
         * 数据格式化
         */
        @Override
        public String toString() {
            return "( " + this.index() + " , " + this.value() + " )";
        }

        /**
         * 获取值类型
         * 
         * @param <T>       idxvalues 列表元素的类型
         * @param <K>       索引键类型
         * @param <V>       索引值类型
         * @param <SELF>    基泛型的派生类型额前向引用
         * @param idxvalues 索引键-值列表
         * @return 索引值类型的Optional
         */
        public static <K, V, SELF, T extends IVPair<K, V, SELF>> Optional<Class<K>> fstclass(
                final List<T> idxvalues) {

            return idxvalues.stream().map(IVPair::class1).dropWhile(Objects::isNull).findFirst();
        }
        
        /**
         * 获取值类型
         * 
         * @param <T>       idxvalues 列表元素的类型
         * @param <K>       索引键类型
         * @param <V>       索引值类型
         * @param <SELF>    基泛型的派生类型额前向引用
         * @param idxvalues 索引键-值列表
         * @return 索引值类型的Optional
         */
        public static <K, V, SELF, T extends IVPair<K, V, SELF>> Optional<Class<V>> sndclass(
                final List<T> idxvalues) {

            return idxvalues.stream().map(IVPair::class2).dropWhile(Objects::isNull).findFirst();
        }

        /**
         * 获取索引值列表的 索引键流
         * 
         * @param <T>       idxvalues 列表元素的类型
         * @param <K>       索引键类型
         * @param <V>       索引值类型
         * @param <SELF>    基泛型的派生类型额前向引用
         * @param idxvalues 索引键-值列表
         * @return 索引值列表idxvalues的 索引键流
         */
        public static <K, V, SELF, T extends IVPair<K, V, SELF>> Stream<K> stream1(final List<T> idxvalues) {

            return idxvalues.stream().map(IVPair::index);
        }

        /**
         * 获取索引值列表的 索引值流
         * 
         * @param <T>       idxvalues 列表元素的类型
         * @param <K>       索引键类型
         * @param <V>       索引值类型
         * @param <SELF>    基泛型的派生类型额前向引用
         * @param idxvalues 索引键-值列表
         * @return 索引值列表idxvalues的 索引值流
         */
        public static <K, V, SELF, T extends IVPair<K, V, SELF>> Stream<V> stream2(final List<T> idxvalues) {

            return idxvalues.stream().map(IVPair::value);
        }

        /**
         * 数据分析，将源数据列表tt做索引键值分析, 提取索引键值结构IVP并生成IVP结构的数据列表
         * 
         * @param <T>           tt 源数据列表中的元素类型
         * @param <K>           索引键类型
         * @param <V>           索引值类型
         * @param <SELF>        基泛型的派生类型额前向引用
         * @param <IVP>         IdxValPair的派生类型
         * @param tt            索引键-值列表
         * @param indexer       索引生成器:t->k
         * @param valueer       值生成器:t->v
         * @param ivp_creator   IVP的生成器:(index,value)->ivp
         * @param ivp_regulator 会在最终提交 ivp值对象之间进行回调，所以可以 在ivp_callback中做一点ivp的调节操作。
         * @return IVP 类型的流
         */
        public static <K, V, SELF, IVP extends IVPair<K, V, SELF>, T> Stream<IVP> analyze(final List<T> tt,
                final Function<T, K> indexer, final Function<T, V> valueer, final BiFunction<K, V, IVP> ivp_creator,
                final Consumer<IVP> ivp_regulator) {

            return analyze(tt, indexer, valueer, ivp_creator, ivp -> {
                ivp_regulator.accept(ivp);
                return ivp;
            });
        }

        /**
         * 数据分析，将源数据列表tt做索引键值分析, 提取索引键值结构IVP,然后对IVP应用 mapper获取目标结构U的数据列表 核心函数 <br>
         * 
         * @param <T>         tt 源数据列表中的元素类型
         * @param <K>         索引键类型
         * @param <V>         索引值类型
         * @param <SELF>      基泛型的派生类型额前向引用
         * @param <IVP>       IdxValPair的派生类型
         * @param <U>         发挥结果的元素类型
         * @param tt          索引键-值列表
         * @param indexer     索引生成器:t->k
         * @param valueer     值生成器:t->v
         * @param ivp_creator IVP的生成器:(index,value)->ivp
         * @param mapper      IVP 到 U的变换函数:ivp->u
         * @return U 类型的流
         */
        public static <K, V, SELF, IVP extends IVPair<K, V, SELF>, T, U> Stream<U> analyze(final List<T> tt,
                final Function<T, K> indexer, final Function<T, V> valueer, final BiFunction<K, V, IVP> ivp_creator,
                final Function<IVP, U> mapper) {

            return tt.stream().map(e -> ivp_creator.apply(indexer.apply(e), valueer.apply(e))).map(mapper);
        }

        /**
         * 实例构造函数 <br>
         * OF大写是为了避免与后续的继承类(子类)的of方法相冲突,即区别对待的突出这是一个始祖级构造实例方法<br>
         *
         * @param <K>   索引类型
         * @param <V>   值类型
         * @param index 索引
         * @param value 值
         * @return 索引值对儿
         */
        public static <K, V> IVPair<K, V, IVPair<K,V,?>> OF(final K index, final V value) {
            return new IVPair<>(index, value);
        }

        /**
         * 实例构造函数 OF 函数的别名
         *
         * @param <K>   索引类型
         * @param <V>   值类型
         * @param index 索引
         * @param value 值
         * @return 索引值对儿
         */
        public static <K, V> IVPair<K, V, IVPair<K,V,?>> IVP(final K index, final V value) {
            return IVPair.OF(index, value);
        }

        /**
         * 索引键
         */
        protected K _1; // 第一值

        /**
         * 索引值
         */
        protected V _2; // 第二值
        
    }
    
    /**
     * 数据点 <br>
     * 这是对KVPair一种特化的实现,Key 特化为 int[] <br>
     * 
     * @author gbench
     *
     * @param <V> 值的类型
     */
    public static class DataPoint<V> extends IVPair<int[],V,DataPoint<V>> {
        
        /**
         * 数据点
         * @param index 索引，vlaue 的坐标维度
         * @param value 值
         */
        public DataPoint(final int[] index, final V value){
            
            super(index,value);
        }
        
        /**
         * 把当前的Index2Value复制到uu对应的元素位置。
         * 
         * @param vv 矩阵元素
         * @return Index2Value 方便实现链式编程
         */
        public DataPoint<V> assignTo(final V[][][][][][] vv) {
            
            final var index = this.index();
            vv[index[0]][index[1]][index[2]][index[3]][index[4]][index[5]] = value();
            
            return this;
        }
        
        /**
         * 把当前的Index2Value复制到uu对应的元素位置。
         * 
         * @param vv 矩阵元素
         * @return Index2Value 方便实现链式编程
         */
        public DataPoint<V> assignTo(final V[][][][][] vv) {
            
            final var index = this.index();
            vv[index[0]][index[1]][index[2]][index[3]][index[4]] = value();
            
            return this;
        }
        
        /**
         * 把当前的Index2Value复制到uu对应的元素位置。
         * 
         * @param vv 矩阵元素
         * @return Index2Value 方便实现链式编程
         */
        public DataPoint<V> assignTo(final V[][][][] vv) {
            
            final var index = this.index();
            vv[index[0]][index[1]][index[2]][index[3]] = value();
            
            return this;
        }
        
        /**
         * 把当前的Index2Value复制到uu对应的元素位置。
         * 
         * @param vv 矩阵元素
         * @return Index2Value 方便实现链式编程
         */
        public DataPoint<V> assignTo(final V[][][] vv) {
            
            final var index = this.index();
            vv[index[0]][index()[1]][index[2]] = value();
            
            return this;
        }
        
        /**
         * 把当前的Index2Value复制到uu对应的元素位置。
         * 
         * @param vv 矩阵元素
         * @return Index2Value 方便实现链式编程
         */
        public DataPoint<V> assignTo(final V[][] vv) {
            
            final var index = this.index();
            vv[index[0]][index[1]] = value();
            
            return this;
        }
        
        /**
         * 把当前的Index2Value复制到uu对应的元素位置。
         * 
         * @param vv 矩阵元素
         * @return Index2Value 方便实现链式编程
         */
        public DataPoint<V> assignTo(final V[] vv) {
            
            final var index = this.index();
            vv[index[0]] = value();
            
            return this;
        }
        
        /**
         * 数据格式化
         */
        @Override
        public String toString() {
            
            return "( ["+Arrays.stream(this.index()).mapToObj(e->e+"").collect(Collectors.joining(","))+"] , "+this.value()+" )";
        }
        
        /**
         * 数据点
         * @param <V> 值类型
         * @param index 索引，vlaue 的坐标维度
         * @param value 值
         * @return IndexValue
         */
        public static <V> DataPoint<V> of(final int[] index, final V value){
            
            return new DataPoint<>(index,value);
        }
        
    }

    /**
     * 带有权重的值对象
     * 
     * @author gbench
     *
     * @param <T> 值类型
     */
    public static class Weightable<T> extends IVPair<Double,T,Weightable<T>>
    implements Comparable<Weightable<T>> { // 值对儿
    
        /**
         * 构造函数
         * 
         * @param weight 权重
         * @param value  值类型
         */
        public Weightable(final Double weight, final T value) {
            super(weight,value);
        }
    
        /**
         * 权重
         * 
         * @return 权重
         */
        public Double weight() {
            return this._1;
        }
    
        /**
         * 格式化输出
         * @return 格式化文本
         */
        public String toString(){
            final var nf = NumberFormat.getInstance();
            return "(v:"+this._2+" / w:"+nf.format(this.weight())+")";
        }
    
        /**
         * 实例函数
         *
         * @param <T> 值类型
         * @param weight 权重
         * @param value  值类型
         * @return Weightable
         */
        public static <T> Weightable<T> WT(final Double weight, final T value) {
            return new Weightable<>(weight, value);
        }
    
        /**
         * 实例函数 (WT 函数的别名，之所以创建of别名是为了保证:<br>
         * WT只有一个实例[方便做lambda参数],而of可以有多态,多态的of可以会同时适配到一元函数与二元函数造成编译歧义)
         * 
         * @param <T> 值类型
         * @param weight 权重
         * @param value  值类型
         * @return Weightable
         */
        public static <T> Weightable<T> of(final Double weight, final T value) {
            return WT(weight, value);
        }
    
        /**
         * 实例函数,随机权重
         * 
         * @param <T> 值类型
         * @param value 值类型
         * @return Weightable
         */
        public static <T> Weightable<T> of(final T value) {
            return WT(Math.random(), value);
        }
    
        /**
         * 实例函数,指定权重函数
         *
         * @param <T> 值类型
         * @param weighter 权重计算函数 t->num
         * @param value 值类型
         * @return Weightable
         */
        public static <T> Weightable<T> of(final Function<T,Number> weighter, final T value) {
            return WT(weighter.apply(value).doubleValue(),value);
        }
    
        /**
         * 实例函数(of 实例函数的别名)
         * 
         * @param <T> 值类型
         * @param weight 权重
         * @param value  值类型
         * @return Weightable
         */
        public static <T> Weightable<T> WEIGHT(final double weight, final T value) {
            return of(weight, value);
        }
    
        /**
         * 实例函数,随机权重(of 实例函数的别名)
         * 
         * @param <T> 值类型
         * @param value 值类型
         * @return Weightable
         */
        public static <T> Weightable<T> WEIGHT(final T value) {
            return of(value);
        }
    
        /**
         * 实例函数,指定权重函数
         *
         * @param <T> 值类型
         * @param weighter 权重计算函数:t->num
         * @param value 值类型
         * @return Weightable
         */
        public static <T> Weightable<T> WEIGHT(Function<T,Number> weighter,T value) {
            return Weightable.of(weighter.apply(value).doubleValue(),value);
        }
    
        /**
         * 实例的映射函数,指定权重函数 weight function
         *
         * @param <T>      值类型
         * @param weighter 权重计算函数:t->num
         * @return t->wta 的函数
         */
        public static <T> Function<T, Weightable<T>> weightf(final Function<T, Number> weighter) {
            return value -> of(weighter.apply(value).doubleValue(), value);
        }
    }

    /**
     * 区间范围 是空间的构成单元 <br>
     * 代表了特定概念（关键属性，特征）的数量维度 <br>
     * 多个 维度可以 组合在一起 共同的 张成span出一个 多维空间 ,这是是设计Range的初始目标。<br>
     * 我们可在Range 所张成的 空间(采样点数据流)的基础之上进行 点概念 即 向量的构造，<br>
     * 进而 获得 一个有意义 数据结构(空间) <br>
     * 具体的如何组织 请看 span方法。<br>
     * <br>
     * Range的形式结构本质是一个三元组,start开始点包含,end结束点不包含,step粒度/区分度。<br>
     * 
     * <br>
     * 区间范围[start,end) 采样点数据流 的控制结构 即 区间类Range<br>
     * 
     * 区间类Range 的一个有用的用途就是用于 定义 区间范围 采样点 结构, 简称 采样点。 <br>
     * 采样点,这是一个函数化的 for循环 控制结构。可以用来模拟生成 如下的 采样点序列。
     * [start,start+step,start+2*step,...,end) <br>
     * 
     * Range.rg(a,b) 类似于 scala 的 a until b 的表达式语句<br>
     * Range.rG(a,b) 类似于 scala 的 a to b 的表达式语句<br>
     * 
     * @author gbench
     */
    public static class Range {
        
        /**
         * 无限循环 结构:0,1,2,...,Double.MAX_VALUE,... <br>
         * 区间对象(步长默认为1)<br>
         * start 开始数量 默认为 0,inclusive <br>
         * end 截止数量  默认为  Double.MAX_VALUE exclusive <br>
         * 单内部处理 示  Double.MAX_VALUE 为无限大，即 当出现  Double.MAX_VALUE<br>
         * 所以此时生成的流可以被视作一个 for(true){}的循环来使用。
         */
        public Range(){
            
           this(Double.MAX_VALUE);
        }
        
        /**
         * 拷贝构造一个区间对象
         * 
         * @param range 被拷贝的区间对象
         */
        public Range(final Range range){
            
           this(range.start, range.end,range.step);
        }
        
        /**
         * 区间对象(步长默认为1) <br>
         * start 开始数量 默认为0,inclusive <br>
         * @param end 截止数量 exclusive
         */
        public Range(final Number end){
            
           this(0, end);
        }
        
        /**
         * 区间对象(步长默认为1)
         * @param start 开始数量 inclusive
         * @param end 截止数量 exclusive
         */
        public Range(final Number start,final Number end){
            
            this(start,end,1);
        }
        
        /**
         * 区间对象
         * @param start 开始数量 inclusive
         * @param end 截止数量 exclusive
         */
        public Range(final Number start, final Number end, final Number step){
            
            this.start = start;
            this.end = end;
            final var sign = start.doubleValue()<end.doubleValue()?1d:-1d; // 步长符号
            this.step = sign*Math.abs(step.doubleValue());
        }
        
        /**
         * 开始点 <br>
         * 返回浮点类型的开始点
         * @return the start
         */
        public Double start() {
            
            return this.start.doubleValue();
        }
        
        /**
         * 开始点 <br>
         * @return the start
         */
        public Number getStart() {
            
            return start.doubleValue();
        }
        
        /**
         * 设置开始点 <br>
         * @param start the start to set
         * @return Range 本身以方便进行链式编程
         */
        public Range setStart(Number start) {
            
            this.start = start;
            
            return this;
        }
        
        /**
         * 结束点 <br> 
         * 不包含 <br>
         * 返回浮点类型的结束点
         * @return the end
         */
        public Double end() {
            
            return end.doubleValue();
        }
        
        /**
         * 结束点 <br> 
         * @return the end
         */
        public Number getEnd() {
            
            return end;
        }
        
        /**
         * 设置 结束点 <br> 
         * @param end the end to set
         * @return Range 本身以方便进行链式编程
         */
        public Range setEnd(final Number end) {
            
            this.end = end;
            
            return this;
        }
        
        /**
         * 采样间隔<br>
         * 返回浮点类型的采样间隔
         * @return the step
         */
        public Double step() {
            
            return step.doubleValue();
        }
        
        /**
         * 采样间隔<br>
         * @return the step
         */
        public Number getStep() {
            
            return step;
        }

        /**
         * 设置 采样间隔<br>
         * @param step the step to set
         * @return Range 本身以方便进行链式编程
         */
        public Range setStep(Number step) {
            
            this.step = step;
            
            return this;
        }
        
        /**
         * Double类型的 采样点序列 数据流
         * 当 end == Double.MAX_VALUE 时候 视为 无限循环
         * @return Double类型的数据流
         */
        public Stream<Double> dblStream(){
            
            return  step.doubleValue() >= 0d
                ? Stream.iterate(start.doubleValue(),
                    i-> end.intValue() == Double.MAX_VALUE || i < end.doubleValue(),
                    i-> i+step.doubleValue())
                : Stream.iterate(start.doubleValue(), 
                    i-> i>end.doubleValue(), 
                    i-> i+step.doubleValue());
        }
        
        /**
         * Integer 类型的  采样点序列 数据流
         * @return Integer类型的数据流
         */
        public Stream<Integer> intStream(){
            
            return this.dblStream().map(Double::intValue);
        }
        
        /**
         * 把向量转换成一个U类型的数据流
         * @param <U> 目标数据类型
         * @param mapper 元素变换器:dbl->u
         * @return U 类型的数据流
         */
        public <U> Stream<U> stream(final Function<Double,U> mapper){
            
            return this.dblStream().map(mapper);
        }

        /**
         * Double类型的 采样点序列 数据流,采用了过滤谓词进行过滤
         * @param bipredicate 过滤谓词：[id,dbl]->true,id 从0开始
         * @return Double类型的数据流
         */
        public Stream<Double> filter(BiPredicate<Long,Double> bipredicate){
            final var al = new AtomicLong(0L);
            return  this.dblStream().filter(x->bipredicate.test(al.getAndIncrement(), x));
        }
        
        /**
         * Double类型的 采样点序列 数据流,采用了过滤谓词进行过滤
         * @param predicate 过滤谓词：[dbl]->true
         * @return Double类型的数据流
         */
        public Stream<Double> filter(Predicate<Double> predicate){
            
            return  this.dblStream().filter(predicate);
        }
        
        /**
         * 开始元素与结束 元素构成的流
         * @return [start,end] 两个元素的流。
         */
        public Stream<Double> startEndS(){
            
            return Stream.of(this.start.doubleValue(),this.end.doubleValue());
        }
        
        /**
         * 转换成  Double[] 数组 <br>
         * dblA的别名 <br> 
         * @return double 数组
         */
        public double[] toArray() {
            
            return this.dblA();
        }
        
        /**
         * 转换成  Double[] 数组 
         * @return Double 数组
         */
        public Double[] toArray2() {
            
            return this.dblStream().toArray(Double[]::new);
        }
        
        /**
         * start 和 end 进行方向调换，更改step的正负号.
         * 对于无限Range的情况，返回null
         * @return [end,start) 的翻转范围 
         */
        public Range reverse() {
            
            if(this.end.doubleValue()==Double.MAX_VALUE) {
                System.out.println("end 为 Double.MAX_VALUE["+this.end()+"],不予方向调换");
                return null;
            }
            return new Range(this.end,this.start,-this.step.doubleValue());
        }

        /**
         * int类型的   采样点序列 数据流
         * @return int 类型的数据流
         */
        public IntStream intS(){
            
            return dblStream().mapToInt(Double::intValue);
        }

        /**
         * long 类型的   采样点序列 数据流
         * @return long 类型的数据流
         */
        public LongStream lngS(){
            
            return dblStream().mapToLong(Double::longValue);
        }

        /**
         * double 类型的   采样点序列 数据流
         * @return double 类型的数据流
         */
        public DoubleStream dblS(){
            
            return dblStream().mapToDouble(Double::doubleValue);
        }

        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据列表
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型数据流
         */
        public <T> List<T> intL(final Function<Integer,T> mapper){
            
            return this.mapInt(mapper).collect(Collectors.toList());
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 列表
         *
         * @return Integer 类型数据流
         */
        public List<Integer> intL(){
            
            return this.intL(e->e);
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 列表
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型数据流
         */
        public <T> List<T> lngL(final Function<Long,T> mapper){
            
            return this.mapLong(mapper).collect(Collectors.toList());
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 列表
         *
         * @return Long 类型数据流
         */
        public List<Long> lngL(){
            
            return this.lngL(e->e);
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 列表
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型数据流
         */
        public <T> List<T> dblL(final Function<Double,T> mapper){
            
            return this.mapDouble(mapper).collect(Collectors.toList());
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 列表
         *
         * @return Double 类型数据流
         */
        public List<Double> dblL(){
            
            return this.dblL(e->e);
        }
        
        /**
         * int类型的   采样点 数组
         * @return int 类型的数组
         */
        public int[] intA(){
            
            return this.intS().toArray();
        }

        /**
         * long 类型的   采样点 数组
         * @return long 类型的 数组
         */
        public long[] lngA(){
            
            return this.lngS().toArray();
        }

        /**
         * double 类型的   采样点 数组
         * @return double 类型数组
         */
        public double[] dblA(){
            
            return this.dblS().toArray();
        }
        
        /**
         * Integer 类型的   采样点 数组
         * @return Integer 类型数组
         */
        public Integer[] intA2(){
            
            return this.intS().boxed().toArray(Integer[]::new);
        }
        
        /**
         * long 类型的   采样点 数组
         * @return Long 类型数组
         */
        public Long[] lngA2(){
            
            return this.lngS().boxed().toArray(Long[]::new);
        }
        
        /**
         * Double 类型的   采样点 数组
         * @return Double 类型数组
         */
        public Double[] dblA2(){
            
            return this.dblS().boxed().toArray(Double[]::new);
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 数组
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型的数组
         */
        @SuppressWarnings("unchecked")
        public <T> T[] dblA2(final Function<Double,T> mapper){

            final var ar = new AtomicReference<Class<T>>();
            return this.mapDouble(e->{
                final var t = mapper.apply(e);
                if(t!=null && ar.get()==null)ar.set((Class<T>)t.getClass());
                return t;
            }).toArray(n->(T[])Array.newInstance(ar.get(), n));
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 数组
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型的数组
         */
        @SuppressWarnings("unchecked")
        public <T> T[] intA2(final Function<Integer,T> mapper){

            final var ar = new AtomicReference<Class<T>>();
            return this.mapInt(e->{
                final var t = mapper.apply(e);
                if(t!=null && ar.get()==null)ar.set((Class<T>)t.getClass());
                return t;
            }).toArray(n->(T[])Array.newInstance(ar.get(), n));
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 数组
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型的数组
         */
        @SuppressWarnings("unchecked")
        public <T> T[] lngA2(final Function<Long,T> mapper){
            
            final var ar = new AtomicReference<Class<T>>();
            return this.mapLong(e->{
                final var t = mapper.apply(e);
                if(t!=null && ar.get()==null)ar.set((Class<T>)t.getClass());
                return t;
            }).toArray(n->(T[])Array.newInstance(ar.get(), n));
        }

        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 列表 ,dblL的方法的别名
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型数据流
         */
        public <T> List<T> list(final Function<Double,T> mapper){
            
            return this.dblL(mapper);
        }
        
        /**
         * 使用mapper变换范围生成相应的   采样点序列 数据 列表 ,dblL的方法的别名
         * 
         * @return T 类型数据流
         */
        public List<Double> list(){
            
            return this.dblL();
        }

        /**
         * 生成一个对象Range,首位分别增加同等偏移数量offset
         * @param offset 偏移数量
         * @return 一个新生成的Range对象
         */
        public Range add(final Number offset) {
            
            return Range.of(this.start.doubleValue()+offset.doubleValue(), 
                this.end.doubleValue()+offset.doubleValue());
        }

        /**
         * 生成一个对象Range,首位分别增加同等偏移数量offset
         * @param offset 偏移数量
         * @return 一个新生成的Range对象
         */
        public Range sub(final Number offset) {
            
            return Range.of(this.start.doubleValue()-offset.doubleValue(), 
                this.end.doubleValue()-offset.doubleValue());
        }

        /**
         * 生成一个对象Range,首位分别乘以同等偏移数量scale
         * @param scale 偏移数量
         * @return 一个新生成的Range对象
         */
        public Range mul(final Number scale) {
            
            return Range.of(this.start.doubleValue()*scale.doubleValue(), 
                this.end.doubleValue()*scale.doubleValue());
        }
        
        /**
         * 突变出一个新的对象U.
         * 使用示例:<br>
         * Range.of2(1, 10).mutate(NVec::new) <br>
         * @param <U> 新的对象类型
         * @param mutator 突变方法:dd->u
         * @return 新的对象U
         */
        public <U> U mutate(final Function<Double[],U> mutator) {
            
            return mutator.apply(this.toArray2());
        }

        /**
         * 生成一个对象Range,首位分别乘以同等偏移数量scale
         * @param scale 偏移数量
         * @return 一个新生成的Range对象
         */
        public Range div(final Number scale) {
            
            return Range.of(this.start.doubleValue()/scale.doubleValue(), 
                this.end.doubleValue()/scale.doubleValue());
        }
        
        /**
         * 反向应用的Map<br>
         * T 类型的流
         * 
         * @param <T> 元素类型
         * @param mappers 映射器 集合
         * @return T 类型数据流
         */
        @SafeVarargs
        final public <T> Stream<T> reverseMap(final Function<Range,T> ... mappers){
            
            return Arrays.stream(mappers).map(mapper->mapper.apply(this));
        }
        
        /**
         * 反向应用的FlatMap
         * 用  mapper 变换 生成一个  T 类型的   采样点序列 数据流 
         * @param <T> 元素类型
         * @param mappers 映射器集合
         * @return T 类型的   采样点序列 数据流 
         */
        @SafeVarargs
        final public <T> Stream<T> reverseFlatMap(final Function<Range,Stream<T>> ... mappers){
            
            return Arrays.stream(mappers).flatMap(mapper->mapper.apply(this));
        }
        
        /**
         * 用  mapper 变换 生成一个 T 类型的   采样点序列 数据流 :mapDouble 的别名
         * @param <T> 元素类型
         * @param mapper 映射器: double->T
         * @return T 类型的   采样点序列 数据流
         */
        public <T> Stream<T> map(final Function<Double,T> mapper){
            
            return this.mapDouble(mapper);
        }
        
        /**
         * 带序号的 采样点遍历 <br>
         * 通cs遍历访问 Range范围中的每个 采样点。 <br>
         * 遍历的索引序号从0开始 <br>
         * <br>
         * @param mapper 二元回调函数 (i:索引号,dbl:采样点)->{}
         * @return Range 对象本身已方便实现链式编程
         */
        public <T> Stream<T> map(final BiFunction<Long,Double,T> mapper) {
            
            final var ai = new AtomicLong(0L); // 计数器
            return this.dblStream().map(d->mapper.apply(ai.getAndIncrement(), d));
        }

        /**
         * 区间范围 采样点的 数据变换。
         * @param <T> 返回结果的参数类型，mapper变换的结果类型。
         * @param mapper 二元映射函数 (i:索引号 从0开始,dbl:采样点)->t
         * @return T 类型的 采样点数据流 
         */
        public <T> Stream<T> map2(final BiFunction<Integer,Double,T> mapper) {
            
            final var ai = new AtomicInteger(0); // 计数器
            
            return this.dblStream().map(d->mapper.apply(ai.getAndIncrement(), d));
        }

        /**
         * 2维空间张成器
         * 
         * @param <T> 元素类型
         * @param mapper 维度数据变换器:double->t
         * @return 增加一个 新维度的 tt的数据流,维度比 tt的维度多一个,即2维度 数据流,流的长度为 [start,end)
         */
        @SuppressWarnings("unchecked")
        public <T> Function<T,Stream<T[]>> derived_2d_ctor(final Function<Double,T> mapper){
            
            return t -> this
                .mapDouble(mapper) // 映射成T类型的采样点流 
                .map( e -> { // t和e 合并成一个数组 向量 [t,e]
                    
                    final var ll = Arrays.asList(t,e);// 组合成tt列表
                    final var clazz = ll.stream()
                        .dropWhile(Objects::isNull).findFirst() // 选取非空元素的 类型作为采样点类型T的实际类型。
                        .map(p->(Class<T>)p.getClass())
                        .orElse((Class<T>)Object.class);// 提取元素类型类用于生成数组结构。
                    
                    return ll.toArray(n->(T[])Array.newInstance(clazz, n));
                });// map
        }
        
        /**
         * 2维空间张成器
         * 
         * @return double 类型的   二维数据流
         */
        public Function<Double,Stream<Double[]>> derived_2d_ctor(){
            
            return this.derived_2d_ctor(e->e);
        }

        /**
         * n维空间张成器
         * 
         * @param <T> 元素类型
         * @param mapper 维度数据变换器
         * @return 增加一个 新维度的 tt的数据流,维度比 tt的维度多一个，流的长度为 [start,end)
         */
        public <T> Function<T[],Stream<T[]>> derived_nd_ctor(final Function<Double,T> mapper){
            
            return tt->this.mapDouble(mapper).map(e->{
                final var aa = Arrays.copyOf(tt, tt.length+1);
                aa[aa.length-1]=e;
                return aa;
            });
        }
        
        /**
         * n维空间张成器
         * 
         * @return 增加一个 新维度的 tt的数据流,维度比 tt的维度多一个，流的长度为 [start,end)
         */
        public Function<Double[],Stream<Double[]>> derived_nd_ctor(){
            
            return this.derived_nd_ctor(e->e);
        }
        
        /**
         * 张成多维向量空间 <br>
         * 
         * 使用示例：<br>
         * final var rng = Range.of(2);// 0,1 <br>
         * rng.span(rng.derived_2d_ctor(),rng.derived_nd_ctor(),Range.of(3).derived_nd_ctor()) <br>
         *  .map(Arrays::asList)<br>
         *  .forEach(System.out::println); <br>
         * 
         * @param <T> 向量空间的元素类型
         * @param derived_2d_ctor 2维空间张成器
         * @param derived_nd_ctors n维空间张成器序列
         * @return 依次采用 d_2d_ctor, d_nd_ctors, 进行累计扩展的 n维度 空间。空间的维数为 2+d_nd_ctors。length
         */
        @SafeVarargs
        final public <T> Stream<T[]> span (
            final Function<Double,Stream<T[]>> derived_2d_ctor,
            final Function<T[],Stream<T[]>> ... derived_nd_ctors){
            
            final var identity = this.dblStream().flatMap(derived_2d_ctor); // 初次张成二维空间,然后再用reduce的办法进行空间的迭代累积扩增
            
            // 累加形成N维度空间
            return Arrays.stream(derived_nd_ctors).reduce(identity, (BiFunction<Stream<T[]>, Function<T[], Stream<T[]>>, Stream<T[]>>) Stream::flatMap, Stream::concat);
        }

        /**
         * 用  mapper 变换 生成一个 T 类型的   采样点序列 数据流 :flatMapDouble 的别名
         * @param <T> 元素类型
         * @param mapper 映射器:Double->[tt]
         * @return T 类型的   采样点序列 数据流
         */
        public <T> Stream<T> flatMap(final Function<Double,Stream<T>> mapper){
            
            return this.flatMapDouble(mapper);
        }
        
        /**
         * 用  mapper 变换 生成一个 T 类型的   采样点序列 数据流
         * 
         * @param <T> 元素类型
         * @param mapper 映射器:int->t
         * @return T 类型的   采样点序列 数据流
         */
        public <T> Stream<T> mapInt(final Function<Integer,T> mapper){
            
            return this.dblStream().map(Double::intValue).map(mapper);
        }
        
        /**
         * 用  mapper 变换 生成一个 T 类型的   采样点序列 数据流
         * 
         * @param <T> 元素类型
         * @param mapper 映射器:int->[tt]
         * @return T 类型的   采样点序列 数据流
         */
        public <T> Stream<T> flatMapInt(final Function<Integer,Stream<T>> mapper){
            
            return this.dblStream().map(Double::intValue).flatMap(mapper);
        }
        
        /**
         * 用  mapper 变换 生成一个 T 类型的   采样点序列 数据流
         * 
         * @param <T> 元素类型
         * @param mapper 映射器:long->t
         * @return T 类型的   采样点序列 数据流
         */
        public <T> Stream<T> mapLong(final Function<Long,T> mapper){
            
            return this.dblStream().map(Double::longValue).map(mapper);
        }
        
        /**
         * 用  mapper 变换 生成一个 T 类型的   采样点序列 数据流
         * 
         * @param <T> 元素类型
         * @param mapper 映射器:long->[tt]
         * @return T 类型的   采样点序列 数据流
         */
        public <T> Stream<T> flatMapLong(final Function<Long,Stream<T>> mapper){
            
            return this.dblStream().map(Double::longValue).flatMap(mapper);
        }
        
        /**
         * T 类型的   采样点序列 数据流
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型的   采样点序列 数据流
         */
        public <T> Stream<T> mapDouble(final Function<Double,T> mapper){
            
            return this.dblStream().map(mapper);
        }
        
        /**
         * T 类型的   采样点序列 数据流
         * 
         * @param <T> 元素类型
         * @param mapper 映射器
         * @return T 类型的   采样点序列 数据流
         */
        public <T> Stream<T> flatMapDouble(final Function<Double,Stream<T>> mapper){
            
            return this.dblStream().flatMap(mapper);
        }
        
        /**
         * 采样点遍历 <br>
         * 通cs遍历访问 Range范围中的每个 采样点。
         * @param cs 回调函数 dbl->{}
         * @return Range 对象本身已方便实现链式编程
         */
        public Range forEach(final Consumer<Double> cs) {
            
            this.dblStream().forEach(cs);
            
            return this;
        }
        
        /**
         * 带序号的 采样点遍历 <br>
         * 通cs遍历访问 Range范围中的每个 采样点。 <br>
         * 遍历的索引序号从0开始 <br>
         * <br>
         * @param cs 二元回调函数 (i:索引号,dbl:采样点)->{}
         * @return Range 对象本身已方便实现链式编程
         */
        public Range forEach(final BiConsumer<Long,Double> cs) {
            
            final var ai = new AtomicLong(0L); // 计数器
            this.dblStream().forEach(d->cs.accept(ai.getAndIncrement(), d));
            
            return this;
        }
        
        /**
         * 使用collector将范围归集为目标对象 
         * @param <A> 积累器的类型accumulation
         * @param <R> 返回的结果
         * @param collector 归集器
         * @return R类型的对象
         */
        public <A,R> R collect(final Collector<Double,A,R> collector) {
            
            return this.dblStream().collect(collector);
        }
        
        /**
         * 设置开始点 <br>
         * @param offset 开始点的偏移,null 视作 不做偏移
         * @return 一个新生成的Range对象,start比当前的对象的start多了一个offset的偏移
         */
        public Range offsetStart(final Number offset) {
            
            return offset(offset,null,null);
        }

        /**
         * 设置开始点 <br>
         * @param offset 终止点的偏移,null 视作 不做偏移
         * @return 一个新生成的Range对象,end比当前的对象的end多了一个offset的偏移
         */
        public Range offsetEnd(final Number offset) {
            
            return offset(null,offset,null);
        }

        /**
         * 设置开始点 <br>
         * @param offset step的偏移,null 视作 不做偏移
         * @return 一个新生成的Range对象,end比当前的对象的end多了一个offset的偏移
         */
        public Range offsetStep(final Number offset) {
            
            return offset(null,null,offset);
        }
        
        /**
         * 对一个Range对象进行偏移操作，生成一个新的Range对象。
         * @param startof 开始点偏移,null 视作 不做偏移
         * @param endof 终止点偏移,null 视作 不做偏移
         * @return 一个新生成的Range对象<br>
         * start比当前的对象的start多了一个offset的偏移
         * end比当前的对象的end多了一个offset的偏移
         */
        public Range offset(final Number startof, final Number endof) {
            
            return offset(startof,endof,null);
        }
        
        /**
         * 构造出一个可以容纳有 n个采样点 区间范围。<br>
         * 采用P2算法实现，尾节点给予包含<br>
         * 
         * 示例:<br>
         * Range.of(PI,-PI).limit(5).forEach((i,e)->{System.out.println(i+"--->"+e);}); <br>
         * 0--->3.141592653589793 <br>
         * 1--->1.5707963267948966 <br>
         * 2--->0.0 <br>
         * 3--->-1.5707963267948966 <br>
         * 4--->-3.141592653589793 <br>
         * @param size 采样点的数量
         * @return 新的而区间对象
         */
        public Range limit(final Number size) {
            
            if(size.doubleValue()<1) {
                System.err.println("采样点数量size不能小于1,复制拷贝当前Range对象给予返回");
                return new Range(this);
            }
            
            return P2(this.start,this.end,size);
        }
        
        /**
         * Range对象格式化
         */
        public String toString() {
            return "("+start+","+end+","+step+")";
        }

        /**
         * 对一个Range对象进行偏移操作，生成一个新的Range对象。
         * @param startof 开始点偏移,null 视作 不做偏移
         * @param endof 终止点偏移,null 视作 不做偏移
         * @param stepof 步长偏移,null 视作 不做偏移
         * @return 一个新生成的Range对象<br>
         * start比当前的对象的start多了一个offset的偏移
         * end比当前的对象的end多了一个offset的偏移
         * step比当前的对象的end多了一个offset的偏移
         */
        public Range offset(final Number startof, final Number endof, final Number stepof) {
            
            return Range.of(
                this.start()+(startof==null?0d:startof.doubleValue()),
                this.end()+(endof==null?0d:endof.doubleValue()),
                this.step()+(stepof==null?0d:stepof.doubleValue())
            );
        }
        
        /**
         * 
         * @param <T> 元素占位符类型
         * @param ll 元素列表
         * @param inheritances 继承关系 <br>
         *                     {(父类superClass,[子类集合subClasses])}，非空表示使用inheritances中的继承关系做异质类型检测,并完成基类型的判断获取
         * @return ll 的元素的共同基类
         */
        @SuppressWarnings("unchecked")
        public static <T> Class<T> getSuperClass(final List<T> ll,final HashMap<Class<?>, Set<Class<?>>> inheritances){
            
            final boolean check_heterogeneous = inheritances != null;
            Class<T> componentType = null; // 元素类型
            if (!check_heterogeneous) { // 没有启动check_heterogeneous则采取第一元素类型作为数组类型
                componentType = ll.stream().filter(Objects::nonNull).map(e -> (Class<T>) e.getClass()).findAny().orElse((Class<T>) Object.class);
            } else { // 开启了异质类型检查
                final var classes = ll.stream().filter(Objects::nonNull).map(e -> (Class<T>) e.getClass()).collect(Collectors.toSet()); // 类型种类集合
                if (classes.size() == 1) {
                    componentType = (Class<T>) classes.iterator().next();
                } else if (classes.size() > 1) {
                    for (final var entry : inheritances.entrySet()) {
                        final var superClass = entry.getKey(); // 父类型
                        final var subClasses = entry.getValue(); // 子类行集合
                        final var b = classes.stream().filter(cls -> !subClasses.contains(cls)).findFirst().orElse(null); // 非空表示 与 分组 e 不匹配
                        if (b == null) { // 没有发现subClasses之外的例外类，说明classes是superClass的子类型，可以使用superClass做为数组类型
                            componentType = (Class<T>) superClass;// 设定数组类型为superClass
                            break;
                        }// if b
                    }// for entry
                }//if classes
            }// if check_heterogeneous
            
            if (componentType == null) componentType = (Class<T>) Object.class; // 默认类型为 Object
            
            return componentType;
        }

        /**
         * Array Collector : 对一个 List<T> 进行归纳: ss 表示 mapper 是一个流Stream->U
         * 
         * @param <T>          归纳元素类型
         * @param <U>          返回结果类型
         * @param mapper       流变换函数 [t] -> U
         * @param inheritances 继承关系 <br>
         *                     {(父类superClass,[子类集合subClasses])}，非空表示使用inheritances中的继承关系做异质类型检测,并完成基类型的判断获取
         * @return U 类型结果的Array Collector对象
         */
        @SuppressWarnings("unchecked")
        public static <T, U> Collector<T, ?, U> aaclc(final Function<T[], U> mapper, final HashMap<Class<?>, Set<Class<?>>> inheritances) {
            
            return Collector.of( ArrayList::new,List::add, (aa, bb) -> { aa.addAll(bb);return aa; },
                ll -> mapper.apply(ll.toArray(n -> {
                    return (T[]) Array.newInstance(getSuperClass(ll,inheritances), n);
                })) // apply
            );// Collector
        }

        /**
         * Array Collector : 对一个 List<T> 进行归纳: ss 表示 mapper 是一个流Stream->U
         * 
         * @param <T>    归纳元素类型
         * @param <U>    返回结果类型
         * @param mapper 流变换函数 tt-> U
         * @return U 类型结果的Array Collector对象
         */
        public static <T, U> Collector<T, ?, U> aaclc(final Function<T[], U> mapper) {
            final List<Class<?>> numClass = Arrays.asList(Integer.class, Long.class, Float.class, Double.class,
                    Short.class); // 数字类型的类
            final var inheritances = new HashMap<Class<?>, Set<Class<?>>>(); // 父级类型集合 {(父类型superClass,子类集合:subClasses)}
            inheritances.put(Number.class, new HashSet<>(numClass)); // 数字类型的 父子类关系
            return aaclc(mapper, inheritances);
        }
        
        /**
         * 全排列 成一个  dims[0] x  dims[1] x ... x dims[n] 的数值空间<br>
         * 
         * 比如:Range.cph(2,2) 生成也给如下的结构<br>
         * [0, 0] <br>
         * [0, 1] <br>
         * [1, 0] <br>
         * [1, 1] <br>
         * 
         * @param dims 空间维度列表,大于0的整数序列。比如 2,2,2 生成一个 2x2x2的cube结构 
         * @return 全排列 成一个  dims[0] x  dims[1] x ... x dims[n] 的数值空间
         */
        @SuppressWarnings("unchecked")
        public static Stream<int[]> cph(final Integer ... dims){
            
            if(dims==null || dims.length<1) return Stream.of();// dims 为空或 长度为0,返回一个空的流
                
            final var tup = Seq.split(dims, 2);// 分拆成 这样的结构: [[0,1],[2,3,...]]
            if(tup.size()>1) {// 分解成功,dims 长度 >=3
                final var header = tup.get(0);// 前半段
                final var tail = tup.get(1);// 后半段
                final var derived_2d_ctor = new Range(header[1]).derived_2d_ctor();// 二维增扩器
                final var derived_nd_ctors = Arrays.stream(tail).map(Range::new).map(Range::derived_nd_ctor)
                    .toArray(n->(Function<Double[],Stream<Double[]>>[])Array.newInstance(Function.class, n)); // n维度增扩器集合
                final var rng = new Range(header[0]);// header[0] 作为增长主轴。
                final var stream = rng.span(derived_2d_ctor, derived_nd_ctors);// 展开向量空间。
                
                return stream.map(NVec::of).map(NVec::ints);
            }else {// dims 长度 小于等于2，即 <3
                if(dims.length<2) // dims 的维度为 1
                    return Range.of(dims[0]).intS().mapToObj(e->new int[]{e});
                else  // dims长度为 2
                    return Range.of(dims[0]).span(Range.of(dims[1]).derived_2d_ctor())
                        .map(NVec::of).map(NVec::ints);
            }
        }
        
        /**
         * 全排列 成一个  dims[0] x  dims[1] x ... x dims[n] 的数值空间<br>
         * 
         * 比如:Range.cph(2,2) 生成也给如下的结构<br>
         * [0, 0] <br>
         * [0, 1] <br>
         * [1, 0] <br>
         * [1, 1] <br>
         * 
         * @param dims 空间维度列表,大于0的整数序列。比如 2,2,2 生成一个 2x2x2的cube结构 
         * @return 全排列 成一个  dims[0] x  dims[1] x ... x dims[n] 的数值空间
         */
        public static Stream<int[]> cph2(final int ... dims){
            
            return cph(Arrays.stream(dims).boxed().toArray(Integer[]::new));
        }

        /**
         * 全排列 成一个  dims[0] x  dims[1] x ... x dims[n] 的数值空间<br>
         * 
         * 比如:Range.cph(2,2) 生成也给如下的结构<br>
         * [0, 0] <br>
         * [0, 1] <br>
         * [1, 0] <br>
         * [1, 1] <br>
         * 
         * @param dims 空间维度列表,NVec包装的对象,大于0的整数序列。比如 2,2,2 生成一个 2x2x2的cube结构 
         * @return 全排列 成一个  dims[0] x  dims[1] x ... x dims[n] 的数值空间
         */
        public static Stream<NVec> cph(NVec dims){
            
            return cph(dims.integers()).map(NVec::of);
        }
        
        /**
         * 构建采样空间<br>
         * 对一组rngs中的采样点做全排序，即定义空间多维空间采样点<br>
         * @param rngs 维度范围集合,采样点范围，维度分量(单元)范围 集合。
         * @return 多维空间采样点集合
         */
        public static Stream<NVec> cph( final Range ... rngs ) {
            
            final Double[][] aa = Arrays.stream(rngs).map(Range::dblA2).toArray(Double[][]::new);
            return cph(aa);
        }
        
        /**
         * 构建采样空间<br>
         * 对一组rngs中的采样点做全排序，即定义空间多维空间采样点<br>
         * @param vv 各个维度的采样点集合。v1,v2,...,分别表示 维度1,维度2上的采样点序列
         * @return 多维空间采样点集合
         */
        public static Stream<NVec> cph( final NVec ... vv ) {
            
            final Double[][] aa = Arrays.stream(vv).map(TVec::toArray).toArray(Double[][]::new);
            return cph(aa);
        }
        
        /**
         * 构建采样空间<br>
         * 对一组rngs中的采样点做全排序，即定义空间多维空间采样点<br>
         * 
         * @param aa 各个维度的采样点集合。a1,a2,...,分别表示 维度1,维度2上的采样点序列
         * @return 多维空间采样点集合
         */
        public static Stream<NVec> cph(final Double[]... aa) {

            final var p = new Permutation<>(aa);
            final var ll = new LinkedList<Double[]>();
            p.permute(e -> ll.add(e.clone()));

            return ll.stream().map(NVec::of);
        }
        
        /**
         * 构建采样空间<br>
         * 对一组rngs中的采样点做全排序，即定义空间多维空间采样点
         * @param rngs 维度范围集合,采样点范围，维度分量(单元)范围 集合。
         * @param cs 结果回调函数,空间的采样点的  回调入口函数,point->{},
         */
        public static void cphx( Consumer<NVec> cs,final Range ... rngs) {
            
            final Double[][] ranges = Arrays.stream(rngs).map(Range::dblA2).toArray(Double[][]::new);
            final var p = new Permutation<>(ranges);
            p.permute(NVec::of,cs);
        }

        /**
         * 构建采样空间<br>
         * 对一组rngs中的采样点做全排序，即定义空间多维空间采样点<br>
         * @param rngs 维度范围集合,采样点范围，维度分量(单元)范围 集合。
         * @param cs 结果回调函数,空间的采样点的  回调入口函数,dd->{},
         */
        public static void cphx2( Consumer<Double[]> cs,final Range ... rngs) {
            
            final Double[][] ranges = Arrays.stream(rngs).map(Range::dblA2).toArray(Double[][]::new);
            final var p = new Permutation<>(ranges);
            p.permute(cs);
        }

        /**
         * 多维数据范围的空间采样点，构建器 <br>
         * 多维数据范围的 空间采样点的 原理就是 构造 每个 采样点范围在 各自维度的 全排列。<br>
         * 采样点范围 的 维度 用 在 空间采样点 拥有一个 唯一且 固定的 索引号。即 point[i]表示第i个维度的 采样点范围 即 与 range[i]相对应。<br>
         * 
         * @author gbench
         *
         * @param <T> 排序的元素类型
         */
        public static class Permutation<T>{
            
            /**
             * 构造以排序结构
             * 
             * ranges[i] 表示 排序结果的定义i个位置所选取的数据范围。 比如:<br>
             * new Double[][]{ <br>
             *    {1,2}, <br>
             *    {3,4} <br>
             * };<br>
             * 将生成一个 如下的 结果:
             * [1.0, 3.0] <br>
             * [1.0, 4.0] <br>
             * [2.0, 3.0] <br>
             * [2.0, 4.0] <br>
             * 
             * @param ranges 是一个 范围定义 结构. <br>
             * 
             */
            @SuppressWarnings("unchecked")
            public Permutation(final T[]... ranges) {

                final var componentType = ranges.getClass().getComponentType().getComponentType();
                this.point = (T[]) Array.newInstance(componentType, ranges.length);
                this.ranges = ranges;
            }

            /**
             * 构造全排列
             * 
             * @param s      开始位置 从0开始
             * @param action 回调函数
             */
            public void permute(final int s, final Consumer<T[]> action) {

                final var e = ranges.length; // 结束位置，是否完成了最终的运算。
                if (s >= e)
                    action.accept(point);
                else {
                    Arrays.asList(ranges[s]).forEach(i -> {
                        point[s] = i;// 在s位置写入i元素
                        permute(s + 1, action);// 然后移步到 下一个位置继续写。
                    });// forEach
                } // if
            }//
            
            /**
             * 构造全排列 <br>
             * 对 ranges进行全排序
             * 
             * @param action 回调函数
             */
            public void permute(final Consumer<T[]> action) {
                this.permute(0, action);
            }
            
            /**
             * 对 ranges进行全排序
             * 
             * @param mapper 数组结构变换器,把 数组类型的tt,变换成一个action可以接受的U的数据类型。tt->u
             * @param action 回调函数
             */
            public <U> void permute(final Function<T[], U> mapper, final Consumer<U> action) {

                this.permute(0, e -> action.accept(mapper.apply(e)));
            }
            
            /**
             * 构造排序组合对象。
             * 
             * @param <T>    元素类型
             * @param ranges 全排列范围
             * @return Permutation 对象
             */
            public static <T> Permutation<T> of(final T[][] ranges) {
                return new Permutation<>(ranges);
            }
            
            private final T[] point;// 结果空间:空间采样点
            private final T[][] ranges; // 排序列表
        }
        
        /**
         * 区段分点构造<br>
         * 构造 维度分点 Points 结构 常用生成绘图区间，比如 <br>
         * final var points = Range.cph(P(0,200,3),P(-PI,PI,5000)).map(matlib.rhotheta2_affine_scale(1, 1/3d)); // 绘制3个椭圆
         * 示例:<br>
         * Range.P(PI,-PI,5).forEach((i,e)->{System.out.println(i+"--->"+e);}); <br>
         * 返回:<br>
         * 0--->3.141592653589793 <br>
         * 1--->1.8849555921538759 <br>
         * 2--->0.6283185307179586 <br>
         * 3--->-0.6283185307179586 <br>
         * 4--->-1.8849555921538759 <br>
         * @param start 开始位置inclusive
         * @param end 结束位置不包含 exclusive
         * @param size 区段分点数量,大于0的正整数, size 等于区间数量,对 start,end之间进行等间隔分区。<br>
         * 即 结果不包含 end分点，若是 加上 e就构成四size+1个分点，所以可以构成n个区段 <br>
         * @return Range对象
         */
        public static Range P(final Number start, final Number end, final Number size) {
            
            final var n = Math.abs(size.doubleValue()); // 区间数量
            final var s = start.doubleValue();
            final var e = end.doubleValue();
            final var p = (end.doubleValue() - start.doubleValue()) / n; // 分为n各区段,连同 e 就构成n个分点了。
            return n > 1
                ? Range.of(s,e,p)
                : Range.of(s,e,e-s);      
        }

        /**
         * 分点构造<br>
         * 构造 维度分点 Points 结构 常用生成绘图区间，比如 <br>
         * final var points = Range.cph(P2(0,200,3),P2(-PI,PI,5000)).map(matlib.rhotheta2_affine_scale(1, 1/3d)); // 绘制3个椭圆
         * <br>
         * 示例:<br>
         * Range.P2(PI,-PI,5).forEach((i,e)->{System.out.println(i+"--->"+e);}); <br>
         * 返回:<br>
         * 0--->3.141592653589793 <br>
         * 1--->1.5707963267948966 <br>
         * 2--->0.0 <br>
         * 3--->-1.5707963267948966 <br>
         * 4--->-3.141592653589793 <br>
         * 
         * @param start 开始位置inclusive
         * @param end 结束位置包含 inclusive
         * @param size 分点数量,大于0的正整数，构成n-1个区段。<br>
         * size 等于分点的数量 要比 对Range进行等间隔区间的数量多一个。<br>
         * 当size=1时只返回开始节点。
         * @return Range对象
         */
        public static Range P2(final Number start, final Number end, final Number size) {
            
            final var n = Math.abs(size.doubleValue()); // 节点数量
            final var s = start.doubleValue(); 
            final var e = end.doubleValue();
            final var p = n > 1 ? (e - s) / (n - 1) : Double.MAX_VALUE;// 区间间隔 period
            return n > 1
                ? Range.of(s,s+p*(n-1)>e?e:e+p,p)
                : Range.of(s,e,e-s);      
        }
        
        /**
         * 正负之间[Negtive,Positive)
         * @param sigma 正区间，负区间的长度
         * @param size 采样点的数量
         * @return [-sigma,-sigma) 区间中 长度为size的采样点序列 
         */
        public static Range NP(final Number sigma,final Number size) {
            return Range.P(-sigma.doubleValue(), sigma.doubleValue(), size);
        }
        
        /**
         * 正负之间:[Negtive,Positive]
         * @param sigma 正区间，负区间的长度
         * @param size 采样点的数量
         * @return [-sigma,-sigma] 区间中 长度为size的采样点序列 
         */
        public static Range NP2(final Number sigma,final Number size) {
            return Range.P2(-sigma.doubleValue(), sigma.doubleValue(), size);
        }
        
        /**
         * 区间对象:[start,end) <br>
         * 标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 标准-不包含 <br>
         * 标准包含状态: start包含,end不包含 <br>
         * 
         * start 开始数量 默认为 0 inclusive <br>
         * @param end 截止数量  exclusive
         */
        public static Range rg(final Number end) {
            return Range.of(end);
        }

        /**
         * 区间对象:[start,end),Range.of的别名 <br>
         * 标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 标准-不包含 <br>
         * 标准包含状态: start包含,end不包含 <br>
         * @param start 开始数量 inclusive
         * @param end 截止数量  exclusive
         */
        public static Range rg(final Number start,final Number end) {
            
            return of(start,end);
        }

        /**
         * 区间对象:[start,end) ,Range.of的别名<br>
         * 标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 标准-不包含 <br>
         * 标准包含状态: start包含,end不包含 <br>
         * @param start 开始数量 inclusive
         * @param end 截止数量  exclusive
         * @param step 步长
         */
        public static Range rg(final Number start,final Number end,final Number step) {
            
            return Range.of(start, end,step);
        }
        
        /**
         * 区间对象(start,end),Range.of1的别名<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含;2#end 标准-不包含
         * 非标准包含状态: start不包含,end不包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * start 开始数量 exclusive 默认为0 <br>
         * @param end 截止数量  exclusive
         * @return 一个新生成的Range对象
         */
        public static Range Rg(final Number end) {
            
            return of1(0,end);
        }

        /**
         * 区间对象(start,end),Range.of1的别名<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含;2#end 标准-不包含
         * 非标准包含状态: start不包含,end不包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量 exclusive
         * @param end 截止数量  exclusive
         * @return 一个新生成的Range对象
         */
        public static Range Rg(final Number start,final Number end) {
            
            return of1(start,end);
        }

        /**
         * 区间对象(start,end),Range.of1的别名<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含;2#end 标准-不包含
         * 非标准包含状态: start不包含,end不包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量 exclusive
         * @param end 截止数量  exclusive
         * @return 一个新生成的Range对象
         */
        public static Range Rg(final Number start,final Number end,final Number step) {
            
            return Range.of1(start, end,step);
        }
        
        /**
         * 区间对象RanGe RG,[start,end],Range.of2的别名<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 非标准-包含
         * 非标准包含状态: start包含,end包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * 开始数量 inclusive 默认为 0 <br>
         * @param end 截止数量  inclusive
         * @return 一个新生成的Range对象
         */
        public static Range rG(final Number end) {
            
            return of2(0,end);
        }

        /**
         * 区间对象RanGe RG,[start,end],Range.of2的别名<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 非标准-包含
         * 非标准包含状态: start包含,end包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量 inclusive
         * @param end 截止数量  inclusive
         * @return 一个新生成的Range对象
         */
        public static Range rG(final Number start,final Number end) {
            
            return of2(start,end);
        }

        /**
         * 区间对象RanGe RG,[start,end],Range.of2的别名<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 非标准-包含 <br>
         * 非标准包含状态: start包含,end包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量 inclusive
         * @param end 截止数量  inclusive
         * @param step_absolute 步长的绝对值
         * @return 一个新生成的Range对象
         */
        public static Range rG(final Number start,final Number end,
            final Number step_absolute) {
            
            return Range.of2(start, end, step_absolute);
        }

        /**
         * 区间对象(start,end]<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含; 2#end 非标准-包含<br>
         * 非标准包含状态: start 不包含,end 包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量  exclusive
         * @param end 截止数量  inclusive
         * @return 一个新生成的Range对象
         */
        public static Range RG(final Number start,final Number end) {
            
            return of12(start,end);
        }

        /**
         * 区间对象(start,end]<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含;2#end 非标准-包含
         * 非标准包含状态: start 不包含,end 包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量  exclusive
         * @param end 截止数量  inclusive
         * @param step_absolute 步长的绝对值
         * @return 一个新生成的Range对象
         */
        public static Range RG(final Number start,final Number end, final Number step_absolute) {
            
            return of12(start,end,step_absolute);
        }

        /**
         * 拷贝构造一个区间对象
         * 
         * @param range 被拷贝的区间对象
         */
        public static Range of (final Range range){
            
           return  new Range(range);
        }
        
        /**
         * 区间对象:[start,end) <br>
         * 标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 标准-不包含 <br>
         * 标准包含状态: start包含,end不包含 <br>
         * start 开始数量 默认为 0 inclusive
         * @param end 截止数量  exclusive
         */
        public static Range of(final Number end) {
            return of(0,end);
        }
        
        /**
         * 区间对象:[start,end) <br>
         * 标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 标准-不包含 <br>
         * 标准包含状态: start包含,end不包含 <br>
         * @param start 开始数量 inclusive
         * @param end 截止数量  exclusive
         */
        public static Range of(final Number start,final Number end) {
            
            final var step = (start.doubleValue()<=end.doubleValue()?1:-1);
            
            return of(start,end,step);
        }
        
        /**
         * 区间对象:[start,end) <br>
         * 标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 标准-不包含 <br>
         * 标准包含状态: start包含,end不包含 <br>
         * @param start 开始数量 inclusive
         * @param end 截止数量  exclusive
         * @param step 步长
         */
        public static Range of(final Number start,final Number end,Number step) {
            
            return new Range(start,end,step);
        }
        
        /**
         * 区间对象(start,end) <br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含;2#end 标准-不包含 <br>
         * 非标准包含状态: start不包含,end不包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量 exclusive
         * @param end 截止数量  exclusive
         * @return 一个新生成的Range对象
         */
        public static Range of1(final Number start,final Number end) {
            
            final var step = (start.doubleValue()<=end.doubleValue()?1:-1);
            
            return of1(start,end,step);
        }

        /**
         * 区间对象(start,end)<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含;2#end 标准-不包含
         * 非标准包含状态: start不包含,end不包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量 exclusive
         * @param end 截止数量  exclusive
         * @param step_absolute 步长的绝对值
         * @return 一个新生成的Range对象
         */
        public static Range of1(final Number start,final Number end,
            final Number step_absolute) {
            
            final var final_step = (start.doubleValue()<=end.doubleValue()?1:-1)
                * Math.abs(step_absolute.doubleValue());// 步长
            
            return new Range(start.doubleValue()+final_step,end,final_step);// 多增加一个步长以保证尾包含
        }

        /**
         * 区间对象[start,end]<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 非标准-包含
         * 非标准包含状态: start包含,end包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量 inclusive
         * @param end 截止数量  inclusive
         * @return 一个新生成的Range对象
         */
        public static Range of2(final Number start,final Number end) {
            
            final var step = (start.doubleValue()<=end.doubleValue()?1:-1);
            
            return of2(start,end,step);
        }
        
        /**
         * 区间对象[start,end]<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 标准-包含;2#end 非标准-包含 <br>
         * 非标准包含状态: start包含,end包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量 inclusive
         * @param end 截止数量  inclusive
         * @param step_absolute 步长的绝对值
         * @return 一个新生成的Range对象
         */
        public static Range of2(final Number start,final Number end,
            final Number step_absolute) {
            
            final var final_step = (start.doubleValue()<=end.doubleValue()?1:-1)
                * Math.abs(step_absolute.doubleValue());// 步长
            
            return new Range(start,end.doubleValue()+final_step,final_step);// 多增加一个步长以保证尾包含
        }
        
        /**
         * 区间对象(start,end]<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含; 2#end 非标准-包含<br>
         * 非标准包含状态: start 不包含,end 包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量  exclusive
         * @param end 截止数量  inclusive
         * @return 一个新生成的Range对象
         */
        public static Range of12(final Number start,final Number end) {
            
            final var step = (start.doubleValue()<=end.doubleValue()?1:-1);
            
            return of12(start,end,step);
        }
        
        /**
         * 区间对象(start,end]<br>
         * 非标准 包含 位置 状态 配置说明: 1#start 非标准-不包含;2#end 非标准-包含
         * 非标准包含状态: start 不包含,end 包含 <br>
         * 带有数字后缀的of表示对应位置上的元素与默认的of处处理方式即半闭半开[start,end)相反。<br>
         * 
         * @param start 开始数量  exclusive
         * @param end 截止数量  inclusive
         * @param step_absolute 步长的绝对值
         * @return 一个新生成的Range对象
         */
        public static Range of12(final Number start,final Number end,
            final Number step_absolute) {
            
            final var final_step = (start.doubleValue()<=end.doubleValue()?1:-1)
                * Math.abs(step_absolute.doubleValue());// 步长
            
            return new Range(start.doubleValue()+final_step,
                end.doubleValue()+final_step,final_step);// 多增加一个步长以保证尾包含
        }
        
        private Number start; // 开始位置
        private Number end; // 结束位置
        private Number step; // 步长
    }

    /**
     * 数据接口只有一个方法data,用于实现Mixin的模式编程
     *
     * @param <T> 元素类型
     */
    @FunctionalInterface
    public interface Data<T> {

        /**
         * 返回向量数据
         *
         * @return [t] T类型的数组
         */
        T[] data();
    }

    /**
     * 序列对象
     * 
     * @param <T> 序列元素类型
     */
    public interface Seq<T> extends Data<T>, Iterable<T>, Comparable<Seq<T>> {

        /**
         * 返回向量数据
         * 
         * @param mapper 映射函数 [t]->u
         * @return U 类型的数据
         */
        default <U> U data(final Function<T[], U> mapper) {
            
            final var data = this.data();
            return mapper.apply(data);
        }

        /**
         * 获取基础元素类型
         * 
         * @return 基础元素类型
         */
        @SuppressWarnings("unchecked")
        default Class<T> getComponentType() {
        
            final var data = this.data();
            if (data == null) return null;

            return (Class<T>) data.getClass().getComponentType();
        }

        /**
         * 向量长度
         * 
         * @return 向量长度
         */
        default int size() {
            
            final var data = this.data();

            return data == null ? 0 : data.length;
        }

        /**
         * 返回第i个元素的值
         * 
         * @param i 索引编号 从0开始，大于等于 data数组长度或是 小于0的索引值，会返回 null的结果。
         * @return T 获取第i元素的值
         */
        default T get(final int i) {
            
            final var data = this.data();
            if (i >= data.length || i < 0)
                return null;
        
            return data[i];
        }

        /**
         * 返回第i个元素的值(对i按照 this.size 进行取模,mode get)
         * 
         * @param i 索引编号 从0开始
         * @return T 获取第i元素的值
         */
        default T mget(final int i) {
            
            final var data = this.data();

            return data[i % data.length];
        }

        /**
         * 提取索引序号路径/序列 中的数据内容
         *
         * @param mapper 结果变换函数: opt&lt;obj&gt;->opt&lt;u&gt;
         * @param idxes  索引序号路径/序列,每个索引序号从0开始
         * @param <U>    结果类型
         * @return U的 Optional 类型结果
         */
        @SuppressWarnings("unchecked")
        default <U> Optional<U> pathget(final Function<Optional<Object>, Optional<U>> mapper, final Number... idxes) {

            final var itr = this.analyze(idxes).reverseIterator();

            if (mapper == null) return (Optional<U>) itr.next();
            else return (itr.hasNext()) ? mapper.apply(itr.next()) : null;
        }

        /**
         * 提取索引序号路径/序列 中的数据内容
         *
         * @param idxes  索引序号路径/序列,每个索引序号从0开始
         * @return U的 Optional 类型结果
         */
        default Optional<Object> pathget(final Number... idxes) {

            return this.pathget(e->e, idxes);
        }

        /**
         * 提取索引序号路径/序列 中的数据内容
         *
         * @param defaultValue 默认值
         * @param idxes        索引序号路径/序列,每个索引序号从0开始
         * @param <U>          结果类型
         * @return U类型的结果,如果idxes索引路径没有数据返回默认值 defaultValue
         */
        @SuppressWarnings("unchecked")
        default <U> U pathget2(final U defaultValue, final Number... idxes) {

            return this.pathget(e->Optional.ofNullable((U)e.orElse(null)), idxes).orElse(defaultValue);
        }

        /**
         * 提取索引序号路径/序列 中的数据内容
         *
         * @param idxes 索引序号路径/序列,每个索引序号从0开始
         * @return Object 类型的结果，如果idxes索引路径没有数据返回null
         */
        default Object pathget2(final Number... idxes) {

            return this.pathget2(null, idxes);
        }

        /**
         * 分析索引序号路径/序列：idxes,把各个索引位置所标定的数据组分 给提取出来,非法的索引序号在组分Seq中返回null <br>
         * 比如一个 3*3*3的列表对象:<br>
         * [ <br>
         * [[0,0,0],[0,0,1],[0,0,2]], [[0,1,0],[0,1,1],[0,1,2]], [[0,2,0],[0,2,1],[0,2,1]], <br>
         * [[1,0,0],[1,0,1],[1,0,2]], [[1,1,0],[1,1,1],[1,1,2]], [[1,2,0],[1,2,1],[1,2,2]], <br>
         * [[2,0,0],[2,0,1],[2,0,2]], [[2,1,0],[2,1,1],[2,1,2]], [[2,2,0],[2,2,1],[2,2,2]] <br>
         * ]<br><br>
         * 按照 analayze(1,1,1) 进行分析 可以获取:<br>
         * [ <br>
         * 第一索引(1)：[[[1,0,0],[1,0,1],[1,0,2]], [[1,1,0],[1,1,1],[1,1,2]], [[1,2,0],[1,2,1],[1,2,2]]], <br>
         * 第二索引(1)：[[1,1,0], [1,1,1], [1,1,2]], <br>
         * 第三索引(1)：[1,1,1] <br>
         * ] <br><br>
         * 实例数据：<br>
         * final var tt = NVec.of(27, i -> i).reshape(3, 3, 3); <br>
         * final var seq = Seq.SEQ(tt, true); <br>
         * println("seq:", seq.format()); <br>
         * seq.analyze(1, 1, 1, 1).map(LittleTree.kvp_int()).forEach(kvp -> { // 多出一个空的维度 <br>
         *     println("comp:",kvp._1(),kvp._2().map(compose_f(Seq::format, Seq::SEQ)).orElse(null)); }); <br>
         * }<br>
         * 返回:
         * seq:	[[[0.0,1.0,2.0],[3.0,4.0,5.0],[6.0,7.0,8.0]],[[9.0,10.0,11.0],[12.0,13.0,14.0],[15.0,16.0,17.0]],[[18.0,19.0,20.0],[21.0,22.0,23.0],[24.0,25.0,26.0]]] <br>
         * comp:	0	[[9.0,10.0,11.0],[12.0,13.0,14.0],[15.0,16.0,17.0]] <br>
         * comp:	1	[12.0,13.0,14.0] <br>
         * comp:	2	[13.0] <br>
         * comp:	3	null <br>
         *
         * @param idxes 索引序号路径/序列,每个索引序号从0开始
         * @return 索引分组数据：每个元素都是一个 Optional
         */
        @SuppressWarnings("unchecked")
        default Seq<Optional<Object>> analyze(final Number... idxes) {

            final var components = new Object[idxes.length];// 分析的组分信息
            for (int i = 0; i < components.length; i++) { // 沿着索引依次分析
                final var idx = idxes[i].intValue(); // 提取第i个阶层的索引
                if (i == 0) { // 首个元素
                    components[0] = this.get(idx); // 首个元素直接索引访问
                } else { // 含有有效前驱的元素
                    final var previous = components[i - 1]; // 前一个元素
                    // 前一个元素无效 或前一个元素 非集合类放弃进一步探查
                    if (previous == null || (!previous.getClass().isArray() && !(previous instanceof Seq))) { //
                        break;
                    } else { // 前一个数据有效则继续向下探查
                        // 注意：obj2seq 会把单个对象转换成一个只有一个元素的Seq，例如 obj会转换成 [obj]给予返回
                        final var seq = SEQ(previous); // seq转换
                        components[i - 1] = seq; // 更新上层结构数据
                        components[i] = seq.get(idx); // 返回本层数据
                    }//if previous
                }// if i
            }// for

            // 生成一个Seq匿名类对象
            return () -> Arrays.stream(components).map(Optional::ofNullable).toArray(Optional[]::new);
        }

        /**
         * 提取首位元素
         * 
         * @return 首位元素
         */
        default T car() {
            
            return this.data()[0];
        }

        /**
         * 提取去除了首位元素后的其余元素序列
         * 
         * @return 除了首位元素后的其余元素序列
         */
        default T[] cdr() {
            
            final var data = this.data();
            return Arrays.copyOfRange(data, 1, data.length);
        }

        /**
         * 提取 末位元素
         * 
         * @return 末位元素
         */
        default T last() {
            
            final var data = this.data();
            if (this.size() < 1)
                return null;
            return data[this.size() - 1];
        }

        /**
         * 提取 去除末位元素后的 其余元素序列
         * 
         * @return 去除末位元素后的 其余元素序列
         */
        default T[] initial() {
            
            final var data = this.data();
            return Arrays.copyOfRange(data, 0, data.length - 1);
        }
        
        /**
         * Copies the specified range of the specified array into a new array
         * 
         * @param from the initial index of the range to be copied, inclusive 从0开始
         * @param to   the final index of the range to be copied, exclusive.(This index
         *             may lie outside the array.)
         * @return Copies the specified range of the specified array into a new array
         */
        default T[] ofRange(final Number from, final Number to) {

            return this.ofRange(from, to, e -> e);
        }

        /**
         * Copies the specified range of the specified array into a new array
         * 
         * @param <U>    结果类型
         * @param from   the initial index of the range to be copied, inclusive 从0开始,null 默认为 0
         * @param to     the final index of the range to be copied, exclusive.(This
         *               index may lie outside the array.) null 默认为 序列长度 即 this.size()
         * @param mapper [t]->u 结果变换函数
         * @return Copies the specified range of the specified array into a new array
         */
        default <U> U ofRange(final Number from, final Number to, Function<T[], U> mapper) {

            final var data = this.data();
            final var _from = from == null ? 0 : from.intValue();
            final var _end = to == null ? this.size() : to.intValue();
            final var tt = Arrays.copyOfRange(data, _from, _end);

            return mapper.apply(tt);
        }

        /**
         * 是否包含元素 t
         *
         * @param t 元素对象
         * @return 是否包含元素 t,true 包含,false 不包含
         */
        default boolean contains(final T t) {
            
            if (t == null) return false;
            return this.stream().filter(e -> e.equals(t)).findFirst().isPresent();
        }

        /**
         * 突变出一个新的对象U
         *
         * @param <U>     新的对象类型
         * @param mutator 突变方法 [t] -> u
         * @return 新的对象U
         */
        default <U> U mutate(final Function<T[], U> mutator) {

            return mutator.apply(Arrays.copyOf(this.data(), this.size()));
        }
        
        /**
         * 突变出一个新的对象U
         *
         * @param <SELF>     对象本身
         * @param <U>     新的对象类型
         * @param mutator 突变方法 self -> u
         * @return 新的对象U
         */
        @SuppressWarnings("unchecked")
        default <SELF extends Seq<T>, U> U mutateT(final Function<SELF, U> mutator) {

            return mutator.apply((SELF) this);
        }

        /**
         * 返回向量数据:拷贝生成一个新的数组
         * 
         * @return 向量数据
         */
        default T[] toArray() {
            
            final var data = this.data();
            return Arrays.copyOf(data, data.length);
        }

        /**
         * 创建一个多维数组空间
         * 
         * @param dims 维度序列
         * @return 多维数组
         */
        default Object newArray(final int... dims) {
            
            return Array.newInstance(this.getComponentType(), dims);
        }

        /**
         * 创建一个多维数组空间
         * 
         * @param dims 维度序列
         * @return 多维数组
         */
        default Object newArray(final Seq<? extends Number> dims) {
            
            final var aa = dims.data(dd -> Arrays.stream(dd).mapToInt(Number::intValue).toArray());
            return Array.newInstance(this.getComponentType(), aa);
        }

        /**
         * 把向量转换成一个T类型的数据流
         * 
         * @return T类型的数据流
         */
        default Stream<T> stream() {
            
            final var data = this.data();
            return data == null ? Stream.of() : Arrays.stream(data);
        }

        /**
         * 把向量转换成一个U类型的数据流
         * 
         * @param <U>    目标数据类型
         * @param mapper 元素变换器:t->u
         * @return U 类型的数据流
         */
        default <U> Stream<U> stream(final Function<T, U> mapper) {

            return this.stream().map(mapper);
        }

        /**
         * 把向量转换成一个U类型的数据流
         * 
         * @param <U>    目标数据类型
         * @param mapper 元素变换器:(i:索引序号从0开始,t:数据元素)->u
         * @return U 类型的数据流
         */
        default <U> Stream<U> stream(final BiFunction<Long, T, U> mapper) {
            
            final var al = new AtomicLong(0L);
            return this.stream().map(t -> mapper.apply(al.getAndIncrement(), t));
        }

        /**
         * 把向量转换成一个T类型的数据流(逆序）
         *
         * @return T类型的数据流
         */
        default Stream<T> reverseStream() {
        
            final var splitter = Spliterators.spliteratorUnknownSize(this.reverseIterator(),Spliterator.ORDERED);
            return StreamSupport.stream(splitter, false);
        }

        /**
         * 使用mapper转换集合data数据，生成u类型的数据流
         * 
         * @param <U>    结果的元素类型
         * @param mapper 数据流映射函数,t->u
         * @return U类型的数据流
         */
        default <U> Stream<U> map(final Function<T, U> mapper) {
            
            final var data = this.data();
            return Arrays.stream(data).map(mapper);
        }

        /**
         * 使用mapper转换集合data数据，生成u类型的数据流
         * 
         * @param <U>    结果的元素类型
         * @param mapper 数据流映射函数,(i:从0开始,t:数据元素)->u
         * @return U类型的数据流
         */
        default <U> Stream<U> map(final BiFunction<Long, T, U> mapper) {
            
            final var al = new AtomicLong(0L);
            final var data = this.data();

            return Arrays.stream(data).map(e -> mapper.apply(al.getAndIncrement(), e));
        }

        /**
         * 使用mapper转换集合data数据，生成u类型的数据流
         * 
         * @param <U>    结果的元素类型
         * @param mapper 数据流映射函数,t->[u]
         * @return U类型的数据流
         */
        default <U> Stream<U> flatMap(final Function<T, Stream<U>> mapper) {
            
            final var data = this.data();

            return Arrays.stream(data).flatMap(mapper);
        }
        
        /**
         * 使用mapper转换集合data数据，生成u类型的数据流
         * 
         * @param <U>    结果的元素类型
         * @param mapper 数据流映射函数,(i:从0开始,t:数据元素)->[u]
         * @return U类型的数据流
         */
        default <U> Stream<U> flatMap(final BiFunction<Long, T, Stream<U>> mapper) {

            final var data = this.data();
            final var al = new AtomicLong(0L);

            return Arrays.stream(data).flatMap(e -> mapper.apply(al.getAndIncrement(), e));
        }

        /**
         * 改变向量(数组)形状:变成多维数组,或者说不只有一维的数组 <br>
         * 当dims的长度小于1的时候，我们将拷贝一个现有的data（向量数据）作为返回结果。<br>
         * 即：Arrays.copyOf(this.data, dims.length<1?this.size():dims[0]);<br>
         * <p>
         * 用法示例: <br>
         * final var tt = (Double[][][])NVec.of(1,2,3,4,5,6,7,8).reshape(2,2,2); <br>
         * 会产生结构: <br>
         * A            B <br>
         * [1.0, 2.0] [3.0, 4.0] <br>
         * [5.0, 6.0] [7.0, 8.0] <br>
         *
         * @param dims 维度空间长度(大于0的整数)的序列值,第一维度,第二维度,...,第n维
         * @return 新的数组对象, 重新结构后的对象结构
         */
        default Object[] reshape(final Integer... dims) {

            return Seq.RESHAPE(this.data(), dims);
        }

        /**
         * 主要用于不方便提取U的具体类型的情况,比如一个泛型的类型U,无法(方便的)获取实际的class <br>
         * 改变向量(数组)形状:变成多维数组,或者说不只有一维的数组 <br>
         * 当dims的长度小于1的时候，我们将拷贝一个现有的data（向量数据）作为返回结果。<br>
         * 即：Arrays.copyOf(this.data, dims.length<1?this.size():dims[0]); 核心函数<br>
         * 
         * 用法示例: <br>
         * final var tt = (Double[][][])NVec.of(1,2,3,4,5,6,7,8).reshape(2,2,2); <br>
         * 会产生结构: <br>
         * A            B <br>
         * [1.0, 2.0] [3.0, 4.0] <br>
         * [5.0, 6.0] [7.0, 8.0] <br>
         * 
         * @param <U>   结果类型
         * @param typeholder 结果类型的类型类占位符，用于提示编译如何编译返回结果的提示信息，没有具体的计算价值.<br>
         *              例如:reshape((Double[][])null,5,5) 表示返回一个5x5的Double矩阵
         * @param dims  维度空间长度(大于0的整数)的序列值,第一维度,第二维度,...,第n维
         * @return 新的数组对象,重新结构后的对象结构
         */
        @SuppressWarnings("unchecked")
        default <U> U reshape(final U typeholder, final Integer... dims) {
            
            return (U) this.reshape(dims);
        }

        /**
         * 改变向量(数组)形状:变成多维数组,或者说不只有一维的数组 <br>
         * 当dims的长度小于1的时候，我们将拷贝一个现有的data（向量数据）作为返回结果。<br>
         * 即：Arrays.copyOf(this.data, dims.length<1?this.size():dims[0]); 核心函数<br>
         * 
         * 用法示例: <br>
         * final var tt = (Double[][][])NVec.of(1,2,3,4,5,6,7,8).reshape(2,2,2); <br>
         * 会产生结构: <br>
         * A            B <br>
         * [1.0, 2.0] [3.0, 4.0] <br>
         * [5.0, 6.0] [7.0, 8.0] <br>
         * 
         * @param <U>   结果类型
         * @param clazz 结果类型的类型类占位符，用于提示编译如何编译返回结果的提示信息，没有具体的计算价值.<br>
         *              例如:reshape(Double[][].class,5,5) 表示返回一个5x5的Double矩阵
         * @param dims  维度空间长度(大于0的整数)的序列值,第一维度,第二维度,...,第n维
         * @return 新的数组对象,重新结构后的对象结构
         */
        @SuppressWarnings("unchecked")
        default <U> U reshape(final Class<U> clazz, final Integer... dims) {
            
            return (U) this.reshape(dims);
        }
        
        /**
         * 返回数据形状:依据索引序列所排成各个索引维度长度的数字列表。 <br>
         * 数据形状按照car的元素进行估计核算，注意返回的shapehi估计大小，<br>
         * 即假设XVec元素是均质的,统计类型包括:数组,XVec,Collection三类。 <br>
         * <br>
         * 
         * @param <U>    结果类型
         * @param mapper 维度序列 变换函数:[int] -> u
         * @return 当前向量的形状[第一维度,第二维度,...]
         */
        @SuppressWarnings("unchecked")
        default <U> U shape(final Function<Integer[], U> mapper) {
            
            var xx = (Object[]) ((Seq<T>) this).data(); // 当前对象
            final var aa = new ArrayList<Integer>(); // 结果汇总
            while (true) {
                aa.add(xx.length);// 记录当前的维度尺寸
                final var x = xx.length > 0 ? xx[0] : null; // 按照首位元素进行提取
                if (x instanceof Object[]) { // 数组类型
                    xx = ((Object[]) x);
                } else if (x instanceof Seq) { // XVec类型操作
                    xx = (Object[]) ((Seq<T>) x).data();
                } else if (x instanceof Collection) { // Collection 类型
                    final var cc = ((Collection<?>) x).stream().collect(Range.aaclc(e -> e));// 转换成对象数组
                    xx = (Object[]) cc;
                } else {// 进入维度端点：最小的数据元素了，结束了
                    break;
                } // if
            } // while

            return mapper.apply(aa.toArray(Integer[]::new));
        }

        /**
         * reshape 多维数组多维数组变换函数。 <br>
         * 一个 典型的使用例子如下:<br>
         * final var mx =
         * NVec.of(Range.of(size*size).dblA2(e->e%(size+1)==0?1:0)).reshape(BlasMatrix::dmx,size,
         * size); // 单位矩阵 <br>
         * System.out.println(mx);
         * 
         * @param <U>    返回的结果类型
         * @param dims   维度空间长度(大于0的整数)的序列值,第一维度,第二维度,...,第n维
         * @param mapper 多维数组变换函数，由于无法预测用户在实际使用时 输入的dims的长度,所以我们无法准确的给出<br>
         *               mapper参数的具体数据的维度即Object后边有几个[],所以 这里使用一个Object[]来代替（用一个代表一切
         *               ),即至少要有一维的意思。
         * @return 2维度矩阵
         */
        default <U> U reshape(final Function<Object[], U> mapper, final Integer... dims) {

            return mapper.apply(this.reshape(dims));
        }

        /**
         * reshape 多维数组多维数组变换函数。 <br>
         * 一个 典型的使用例子如下:<br>
         * final var mx =
         * NVec.of(Range.of(size*size).dblA2(e->e%(size+1)==0?1:0)).reshapeX(BlasMatrix::dmx,size,
         * size); // 单位矩阵 <br>
         * System.out.println(mx);
         *
         * @param <X>    原数据类型
         * @param <U>    返回的结果类型
         * @param dims   维度空间长度(大于0的整数)的序列值,第一维度,第二维度,...,第n维
         * @param xmapper 多维数组变换函数，由于无法预测用户在实际使用时 输入的dims的长度,所以我们无法准确的给出<br>
         *               mapper参数的具体数据的维度即Object后边有几个[],所以 这里使用一个X类型来代替
         * @return 2维度矩阵
         */
        @SuppressWarnings("unchecked")
        default <X,U> U reshapeX(final Function<X, U> xmapper, final Integer... dims) {

            return xmapper.apply((X) this.reshape(dims));
        }

        /**
         * reshape 1维度的简化函数 <br>
         * 
         * @param a 第一维长度
         * @return 1维数组
         */
        @SuppressWarnings("unchecked")
        default T[] reshape1(final int a) {

            return (T[]) this.reshape(a);
        }

        /**
         * reshape 2维度的简化函数 <br>
         * 
         * @param a 第一维度的长度
         * @param b 第二维度的长度
         * @return 2维数组
         */
        @SuppressWarnings("unchecked")
        default T[][] reshape2(final int a, final int b) {

            return (T[][]) this.reshape(a, b);
        }

        /**
         * reshape 3维度的简化函数 <br>
         * 
         * @param a 第二维度的长度
         * @param b 第二维度的长度
         * @param c 第三维度的长度
         * @return 3维度数组
         */
        @SuppressWarnings("unchecked")
        default T[][][] reshape3(final int a, final int b, final int c) {

            return (T[][][]) this.reshape(a, b, c);
        }

        /**
         * reshape 4维度的简化函数 <br>
         * 
         * @param a 第一维度的长度
         * @param b 第二维度的长度
         * @param c 第三维度的长度
         * @param d 第四维度的长度
         * @return 4维数组
         */
        @SuppressWarnings("unchecked")
        default T[][][][] reshape4(final int a, final int b, final int c, final int d) {

            return (T[][][][]) this.reshape(a, b, c, d);
        }

        /**
         * reshape 5维度的简化函数 <br>
         * 
         * @param a 第一维度的长度
         * @param b 第二维度的长度
         * @param c 第三维度的长度
         * @param d 第四维度的长度
         * @param e 第四维度的长度
         * @return 5维数组
         */
        @SuppressWarnings("unchecked")
        default T[][][][][] reshape5(final int a, final int b, final int c, final int d, final int e) {

            return (T[][][][][]) this.reshape(a, b, c, d, e);
        }

        /**
         * reshape 6维度的简化函数 <br>
         * 
         * @param a 第一维度的长度
         * @param b 第二维度的长度
         * @param c 第三维度的长度
         * @param d 第四维度的长度
         * @param e 第四维度的长度
         * @param f 第四维度的长度
         * @return 6维数组
         */
        @SuppressWarnings("unchecked")
        default T[][][][][][] reshape6(final int a, final int b, final int c, final int d, final int e,
                final int f) {

            return (T[][][][][][]) this.reshape(a, b, c, d, e, f);
        }

        /**
         * reshape 2维度的简化函数 <br>
         * 
         * @param a 第一维度的长度:矩阵的行数
         * @param b 第二维度的长度:矩阵的列数
         * @return 2维度矩阵
         */
        @SuppressWarnings("unchecked")
        default DataMatrix<T> reshape2mx(final int a, final int b) {
        
            return DataMatrix.of((T[][]) this.reshape(a, b), true);
        }

        /**
         * 使用collector将向量归集成目标对象
         * 
         * @param <A>       积累器的类型accumulation
         * @param <R>       返回的结果
         * @param collector 归集器
         * @return R类型的对象
         */
        default <A, R> R collect(final Collector<? super T, A, R> collector) {
            
            return this.stream().collect(collector);
        }

        /**
         * 结果规约
         * 
         * @param accumulator 规约函数：同类型规约函数:(t,t)->t
         * @return T 类型的规约结果：Optional值
         */
        default Optional<T> reduce(final BinaryOperator<T> accumulator) {
        
            return this.stream().reduce(accumulator);
        }

        /**
         * 结果规约
         * 
         * @param identity    初始值
         * @param accumulator 规约函数：同类型规约函数
         * @return T 类型的规约结果
         */
        default T reduce(final T identity, final BinaryOperator<T> accumulator) {

            return this.stream().reduce(identity, accumulator);
        }

        /**
         * 结果规约
         * 
         * @param <U>         结果类型
         * @param identity    初始值 u
         * @param accumulator 规约函数：异类型规约函数(u,t)->u
         * @param combiner    合并函数: (u,u)->u
         * @return T 类型的规约结果
         */
        default <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner) {

            return this.stream().reduce(identity, accumulator, combiner);
        }

        /**
         * 结果规约
         * 
         * @param accumulator 规约函数：同类型规约函数:(t,t)->t
         * @return T 类型的规约结果,当 Optional.empty的时候，返回null
         */
        default T reduce2(final BinaryOperator<T> accumulator) {
        
            return this.stream().reduce(accumulator).orElse(null);
        }

        /**
         * 对T中的元素进行分组
         * 
         * @param <K>        键类型
         * @param classifier 分类器
         * @return 分组结构 Map
         */
        default <K> Map<K, List<T>> groupBy(final Function<? super T, K> classifier) {

            return this.groupBy(classifier, Collectors.toList());
        }

        /**
         * 对T中的元素进行分组
         * 
         * @param <K>        键类型
         * @param <D>        规约的元素类型
         * @param classifier 分类器
         * @param downstream 分组结果的搜集器.a Collector implementing the downstream reduction.
         * @return 分组结构 Map
         */
        default <K, D> Map<K, D> groupBy(final Function<? super T, K> classifier,
                Collector<? super T, ?, D> downstream) {

            return this.stream().collect(Collectors.groupingBy(classifier, downstream));
        }

        /**
         * 对T中的元素进行分组
         * 
         * @param <K>        键类型
         * @param <D>        规约的元素类型
         * @param <R>        返回的结果类型
         * @param classifier 分类器
         * @param downstream 分组结果的搜集器.a Collector implementing the downstream reduction.
         * @param finisher   结果变换器{(k,v)}->u
         * @return R类型的结果
         */
        default <K, D, R> R groupBy(final Function<? super T, K> classifier,
                Collector<? super T, ?, D> downstream, Function<Map<K, D>, R> finisher) {

            return finisher.apply(this.stream().collect(Collectors.groupingBy(classifier, downstream)));
        }
        
        /**
         * Returns a {@link Spliterator} covering all of the Seq data
         *
         * <p>
         * The spliterator reports {@link Spliterator#SIZED},
         * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and
         * {@link Spliterator#IMMUTABLE}.
         *
         * @return a spliterator for the array elements
         */
        default Spliterator<T> spliterator() {
            return Arrays.spliterator(this.data());
        }

        /**
         * 生成一个遍历器(顺序)
         */
        default Iterator<T> iterator() {

            final var ai = new AtomicInteger(0); // 初始化索引编号 从0开始

            return new Iterator<>() { // 索引迭代器
                @Override
                public boolean hasNext() {
                    return ai.get() < Seq.this.size();
                }

                @Override
                public T next() {
                    return Seq.this.get(ai.getAndIncrement());
                }
            };
        }

        /**
         * 生成一个遍历器(逆序)
         */
        default Iterator<T> reverseIterator() {

            final var ai = new AtomicInteger(this.size()-1); // 初始化索引编号 从0开始

            return new Iterator<>() { // 索引迭代器
                @Override
                public boolean hasNext() {
                    return ai.get() >= 0;
                }

                @Override
                public T next() {
                    return Seq.this.get(ai.getAndDecrement());
                }
            };
        }

        /**
         * 转换成 列向量(矩阵 )
         * 
         * @return 数据矩阵 size x 1
         */
        default DataMatrix<T> matrix() {

            return this.matrix(e -> e);
        }

        /**
         * 转换成 列向量(矩阵 )
         * 
         * @param <U>    目标结果的类型
         * @param mapper 矩阵变换函数 mx(size x1)->U
         * @return 数据矩阵 size x 1
         */
        default <U> U matrix(final Function<DataMatrix<T>, U> mapper) {

            return mapper.apply(DataMatrix.of(this.reshape2(this.size(), 1), true));
        }

        /**
         * 数据窗口滑动<br>
         * 对一个:1 2 3 4,按照 size:为2,step为1的参数进行滑动的结果。<br>
         * 
         * | size | 每个窗口大小为 size,每次移动的步长为step<br>
         * [1 2]<br>
         * step0:[2 3]<br>
         * - step1:[3 4]<br>
         * - - step2:[4]<br>
         * 返回:[ [1,2], [2,3], [3,4], [4] ]<br>
         *
         * @param size 滑动的窗口大小
         * @param step 每次移动的步长
         * @return 滑动窗口的列表。
         */
        default List<T[]> sliding(final int size, final int step) {
            return sliding(this.list(), size, step);
        }

        /**
         * 数据窗口滑动<br>
         * 对一个:1 2 3 4,按照 size:为2,step为1的参数进行滑动的结果。<br>
         * 
         * | size | 每个窗口大小为 size,每次移动的步长为step<br>
         * [1 2]<br>
         * step0:[2 3]<br>
         * - step1:[3 4]<br>
         * - - step2:[4]<br>
         * 返回:[ [1,2], [2,3], [3,4], [4] ]<br>
         * 
         * @param <U>    元素的结果类型
         * @param size   滑动的窗口大小
         * @param step   每次移动的步长
         * @param mapper 元素映射器:[t]->u
         * @return 滑动窗口的列表。
         */
        default <U> Stream<U> slidingS(final int size, final int step, final Function<T[], U> mapper) {

            return sliding(this.list(), size, step).stream().map(mapper);
        }

        /**
         * 把向量转换成一个T类型的列表对象
         * 
         * @return T类型的列表对象
         */
        default List<T> list() {

            return Arrays.asList(this.data());
        }

        /**
         * 把向量转换成一个U类型的列表对象
         * 
         * @param mapper 元素变换器
         * @return U类型的列表对象
         */
        default <U> List<U> list(final Function<T, U> mapper) {
            
            final var data = this.data();
            return Arrays.stream(data).map(mapper).collect(Collectors.toList());
        }

        /**
         * 数据切片:按照长度进行切片
         * 
         * @param <U>    列表元素类型
         * @param mapper 结果映射函数 [tt]->U
         * @param sizes  切片尺寸大小,切片尺寸会被循环使用
         * @return 切片集合
         */
        default <U> List<U> slice(final Function<T[], U> mapper, final int... sizes) {

            final int n = this.size(); // 数据长度
            final var nz = sizes.length; // 分片集合的长度
            final var dataL = Arrays.asList(this.data());// 转换成数组类型
            final var ll = new LinkedList<U>();// 返回结果
            final var componentType = this.getComponentType(); // 元素类型

            for (int i = 0, j = 0; i < n; i += sizes[(j++) % nz]) { // i 数据遍历索引,j 分片集合的遍历索引
                final var from = i;// 开始位置
                final var to = i + sizes[j % nz];// 结束位置 不包含
                final var sample = dataL.subList(from, Math.min(to, n));// sublist 截取
                ll.add(mapper.apply(sample.toArray(Seq.aagen(componentType)))); // 数据添加
            } // for

            return ll;
        }
        
        /**
         * 带有数据填充的 数据切片:按照长度进行切片
         * 
         * @param <U>    列表元素类型
         * @param mapper 结果映射函数 [tt]->U
         * @param sizes  切片尺寸大小,切片尺寸会被循环使用
         * @return 切片集合
         */
        default <U> List<T[]> slice2(final int... sizes) {
            return slice2(null, sizes);
        }

        /**
         * 带有数据填充的 数据切片:按照长度进行切片
         * 
         * @param <U>    列表元素类型
         * @param fill   对于不足的元素采用填充的默认值
         * @param mapper 结果映射函数 [tt]->U
         * @param sizes  切片尺寸大小,切片尺寸会被循环使用
         * @return 切片集合
         */
        default <U> List<T[]> slice2(final T fill, final int... sizes) {
            return slice2(fill, e -> e, sizes);
        }

        /**
         * 带有数据填充的 数据切片:按照长度进行切片
         * 
         * @param <U>    列表元素类型
         * @param fill   对于不足的元素采用填充的默认值
         * @param mapper 结果映射函数 [tt]->U
         * @param sizes  切片尺寸大小,切片尺寸会被循环使用
         * @return 切片集合
         */
        default <U> List<U> slice2(final T fill, final Function<T[], U> mapper, final int... sizes) {

            final int n = this.size(); // 数据长度
            final var nz = sizes.length; // 分片集合的长度
            final var dataL = Arrays.asList(this.data());// 转换成数组类型
            final var ll = new LinkedList<U>();// 返回结果
            final var componentType = this.getComponentType(); // 元素类型

            for (int i = 0, j = 0; i < n; i += sizes[(j++) % nz]) { // i 数据遍历索引,j 分片集合的遍历索引
                final var from = i;// 开始位置
                final var len = sizes[j % nz]; // 分片长度
                final var to = i + len;// 结束位置 不包含
                final var sample = dataL.subList(from, Math.min(to, n));// sublist 截取
                final var aa = sample.toArray(Seq.aagen(componentType)); // 数组类型的数据
                final var tt = aa.length < len ? Arrays.copyOf(aa, len) : aa; // 初级数组
                if (fill != null) for (int k = aa.length; k < len; k++) tt[k] = fill; // 填充默认数据

                ll.add(mapper.apply(tt)); // 数据添加
            } // for

            return ll;
        }
        
        /**
         * 对元素序列进行排序
         * 
         * @param weighter 排序的向量的权重函数 t->num <br>
         *                 即把 t映射成一个可以进行比较的数值权重(weight)而后按照weight进行排序：从小打到大
         * @return 排序后的流
         */
        default Stream<T> sortedS(final Function<T, Number> weighter) {
            
            final var data = this.data();
            return Arrays.stream(data).map(Weightable.weightf(weighter)).sorted().map(IVPair::value);
        }
        
        /**
         * 对元素序列进行排序
         * 
         * @param weighter 排序的向量的权重函数 (i:索引序号从0开始,t:数据元素) -> num <br>
         *                 即把 t映射成一个可以进行比较的数值权重(weight)而后按照weight进行排序：从小打到大
         * @return 排序后的流
         */
        default Stream<T> sortedS(final BiFunction<Integer, T, Number> weighter) {

            final var ai = new AtomicInteger(0);
            return this.sortedS(e -> weighter.apply(ai.getAndIncrement(), e));
        }

        /**
         * 数据随机权重,而后给予重排顺序<br>
         * 打乱向量的元素顺序的数据流（数据采用随机权重)
         * 
         * @return 打乱向量的元素顺序的数据流
         */
        default Stream<T> shuffleS() {
            
            return this.shuffleS((Function<T, Weightable<T>>) Weightable::of);
        }

        /**
         * 一元变换:t->weightable <br>
         * 数据随机权重,而后给予重排顺序<br>
         * 把向量转换成一个U类型的数据顺序被打乱的数据流
         * 
         * @param <U>    目标数据类型
         * @param mapper 元素变换器,把T 变换成一个带有权重的 U值 : t -> weightable&lt;u&gt;
         * @return U 类型的数据流
         */
        default <U> Stream<U> shuffleS(final Function<T, Weightable<U>> mapper) {
            
            return this.shuffleS((i, t) -> mapper.apply(t));
        }

        /**
         * 二元变换：(i,t)->weightable<br>
         * 数据随机权重,而后给予重排顺序<br>
         * 把向量转换成一个U类型的数据顺序被打乱的数据流
         *
         * @param <U>    目标数据类型
         * @param mapper 元素变换器,把T 变换成一个带有权重的 U值 : <br>
         *               (i:索引序号从0开始,t:元素值) -> weightable&lt;u&gt;
         * @return U 类型的数据流
         */
        default <U> Stream<U> shuffleS(final BiFunction<Integer, T, Weightable<U>> mapper) {
            
            final var ai = new AtomicInteger(0);
            final var data = this.data();

            return Arrays.stream(data).map(u -> mapper.apply(ai.getAndIncrement(), u)).sorted().map(Weightable::value);
        }

        /**
         * 一元变换:t->weight <br>
         * 数据随机权重,而后给予重排顺序<br>
         * 把向量转换成一个U类型的数据顺序被打乱的数据流
         *
         * @param weighter 排序的向量的权重函数 t->num <br>
         *                 即把 t映射成一个可以进行比较的数值权重(weight)而后按照weight进行排序：从小打到大
         * @return T 类型的数据流
         */
        default Stream<T> shuffleS2(final Function<T, Double> weighter) {
            
            return this.shuffleS((i, t) -> Weightable.of(weighter.apply(t), t));
        }

        /**
         * 数据切片:按照长度进行切片
         * 
         * @param <U>    列表元素类型
         * @param mapper 结果映射函数 [tt]->U
         * @param sizes  切片尺寸大小,切片尺寸会被循环使用
         * @return 切片的流
         */
        default <U> Stream<U> sliceS(final Function<T[], U> mapper, final int... sizes) {

            return this.slice(mapper, sizes).stream();
        }

        /**
         * 一分为二 <br>
         * 
         * @param <U>    列表元素类型
         * @param mapper 结果映射函数 [tt]->U
         * @return 长度为2的切片列表
         */
        default <U> List<U> halves(final Function<T[], U> mapper) {
            return this.halveP(mapper).toList((U)null);
        }

        /**
         * 一分为二 <br>
         * 
         * @param <U>    列表元素类型
         * @param mapper 结果映射函数 [tt]->U
         * @return 长度为2的切片流
         */
        default <U> Stream<U> halveS(final Function<T[], U> mapper) {

            return this.halves(mapper).stream();
        }
        
        /**
         * 一分为二 <br>
         * 
         * @param <U>    列表元素类型
         * @param mapper 结果映射函数 [tt]->U
         * @return (前半片,后半片)
         */
        default <U> IVPair<U,U,IVPair<U,U,?>> halveP(final Function<T[], U> mapper) {
            final var middle = this.size() >>> 1; //中间位置的索引
            final var head = Arrays.copyOfRange(this.data(), 0,middle);// 前头 第一元素 
            final var tail = Arrays.copyOfRange(this.data(), middle,this.data().length);  // 后尾 第二元素
            return IVPair.IVP(mapper.apply(head),mapper.apply(tail)); // 返回结果值
        }
        
        /**
         * 求出两个集合的差
         * 
         * @param other 另一个 Seq 对象
         * @return 集合差对象
         */
        default T[] diffSeq(final Seq<T> other) {

            return this.stream().filter(e -> !other.contains(e)).collect(Range.aaclc(e -> e));
        }

        /**
         * 求出两个集合的合并
         *
         * @param other 另一个 Seq 对象
         * @return 集合差对象
         */
        default T[] unionSeq(final Seq<T> other) {

            return Stream.of(this.stream(), other.stream()).flatMap(e -> e).distinct().collect(Range.aaclc(e -> e));
        }

        /**
         * 求出两个集合的交集
         * 
         * @param other 另一个 Seq 对象
         * @return 集合差对象
         */
        default T[] intersectSeq(final Seq<T> other) {

            return this.stream().filter(other::contains).collect(Range.aaclc(e -> e));
        }

        /**
         * 拉链成流
         * 
         * @param <V>   第二位置元素类型
         * @param <P>   结果元素类型
         * @param seq   第二位置元素序列
         * @param pctor 结果元组构造函数::(k,v)->p
         * @return P类型的二元元组流
         */
        default <V,P extends IVPair<T,V,?>> Stream<P> zipS(final Seq<V> seq, final BiFunction<T,V,P> pctor){

            final var na = this.size();
            final var nb = seq.size();

            return Stream.iterate(0, i->i+1).limit(Math.max(na, nb)).map(i->pctor.apply(this.get(i%na),seq.get(i%nb)));
        }
        
        /**
         * 拉链成流
         * 
         * @param <V> 第二位置元素类型
         * @param seq 第二位置元素序列
         * @return 结果元组构造器
         */
        default <V> Stream<IVPair<T,V,?>> zipS(final Seq<V> seq){

            return this.zipS(seq, IVPair::OF);
        }

        /**
         * 拉链计算成X的流
         * 
         * @param <V>       第二位置元素类型
         * @param <X>       结果元素类型
         * @param seq       第二位置元素序列
         * @param evaluator 结果元素计算函数:(k,v)->p
         * @return P类型的二元元组流
         */
        default <V, X> Stream<X> zipXS(final Seq<V> seq, final BiFunction<T, V, X> evaluator) {

            final var na = this.size();
            final var nb = seq.size();

            return Stream.iterate(0, i -> i + 1).limit(Math.max(na, nb))
                    .map(i -> evaluator.apply(this.get(i % na), seq.get(i % nb)));
        }

        /**
         * 拉链计算成X的流(中间结果),并归集成U类型的结果
         * 
         * @param <V>       第二位置元素类型
         * @param <X>       中间结果的元素类型
         * @param <U>       最终结果类型
         * @param seq       第二位置元素序列
         * @param evaluator 中间结果计算函数:(k,v)->x
         * @param collector 结果汇集器 [x]->u
         * @return U类型的结果
         */
        default <V, X, U> U zipU(final Seq<V> seq, final BiFunction<T, V, X> evaluator, final Collector<X, ?, U> collector) {

            return this.zipXS(seq, evaluator).collect(collector);
        }

        /**
         * 向量大小比较 <br>
         * 把this与seq统一到(resize)最大长度而后按照元素索引顺序(从小到大)进行逐个比较<br>
         * 一旦出现不相等则立即返回,否则一直比较直到结束，<br>
         * 若this,seq的所有元素都相同则返回 0 <br>
         * 注意:<br>
         * TVec的每个元素t需要具有比较能力即 t需要是一个 Comparable&lt;T&gt; 的接口实例,如果T没有实现该接口 则compareTo
         * 会触发异常，并返回 -1
         *
         * @param seq 另一个 Seq 向量
         * @return (this - seq) 即 this[i]-seq[i] 的第一个非0结果 或是 0
         */
        @Override
        @SuppressWarnings("unchecked")
        default int compareTo(final Seq<T> seq) {

            if (seq == null) return 1;
            
            final var na = this.size(); // 当前对象尺寸
            final var nb = seq.size(); // 比较对象尺寸
            final var n = Math.max(na, nb);// 最大长度
            var ret = 0; // 返回结果，默认相等
            
            try {
                for (int i = 0; i < n; i++) {
                    final var ai = (Comparable<T>) (i < na ? this.get(i) : null);
                    final var bi = (T) (i < nb ? seq.get(i) : null);
                    if (ai == null && bi == null) continue;
                    else if (ai == null) return -1;
                    else if (bi == null) return 1;
                    else {
                        ret = ai.compareTo(bi); // 元素比较
                        if (ret != 0)
                            break;
                    } // if
                } // for
            } catch (Exception e) {
                e.printStackTrace();
                ret = -1;
            }

            return ret;
        }

        /**
         * 数据格式化
         *
         * @param formatter 数据格式化
         * @return 字符串
         */
        default String format(final Function<Object, String> formatter) {

            final var line = Arrays.stream(this.data()).map(formatter).collect(Collectors.joining(","));

            return "[" + line + "]";
        }

        /**
         * 数据格式化
         *
         * @return 字符串
         */
        @SuppressWarnings("unchecked")
        default String format() {

            final Function<Object, String> formatter = obj -> {
                if (obj == null) return "null";
                if (obj instanceof Seq)
                    return ((Seq<Object>) obj).format();
                else if (obj.getClass().isArray()) {
                    return Arrays.deepToString((Object[]) obj);
                } else {
                    return obj.toString();
                }
            };

            return this.format(formatter);
        }

        /**
         * 数据切片
         * 
         * @param <T>   列表元素类型
         * @param ll    数据列表
         * @param sizes 切片大小,切片大小需要时大于0的整数。
         * @return 切片集合
         */
        static <T> List<T[]> slice(final List<T> ll, final int... sizes) {
        
            final int n = ll.size();// 元素列表大小。
            final var aa = new ArrayList<>(ll);// 转换成数组类型
            final var res = new LinkedList<T[]>();// 返回结果
            final var componentType = componentType(ll);
            final var zz = Arrays.stream(sizes).filter(e -> e > 0).toArray(); // 提取出多有大于0的项目
            if (zz.length > 0) {
                for (int i = 0, j = 0; i < n; i += zz[j]) {
                    final var from = i;// 开始位置
                    final var to = i + zz[(j++) % zz.length];// 结束位置
                    final var sl = aa.subList(from, Math.min(to, n));// sublist
                    res.add(sl.toArray(aagen(componentType)));
                } // for
            } // if
        
            return res;
        }

        /**
         * 数据窗口滑动<br>
         * 对一个:1 2 3 4,按照 size:为2,step为1的参数进行滑动的结果。<br>
         * 
         * | size | 每个窗口大小为 size,每次移动的步长为step<br>
         * [1 2]<br>
         * step0:[2 3]<br>
         * - step1:[3 4]<br>
         * - - step2:[4]<br>
         * 返回:[ [1,2], [2,3], [3,4], [4] ]<br>
         * 
         * @param <T>  元素类型
         * @param ll   待操作的列表
         * @param size 滑动的窗口大小
         * @param step 每次移动的步长
         * @return 滑动窗口的列表。
         */
        static <T> List<T[]> sliding(final List<T> ll, final int size, final int step) {
        
            final int n = ll.size();
            final var aa = new ArrayList<>(ll);// 转换成数组类型
            final var res = new LinkedList<T[]>();// 返回结果
            final var componentType = componentType(ll);
            for (int i = 0; i < n; i += step) {
                final var from = i;// 开始位置
                final var to = i + size;// 结束位置
                final var sl = aa.subList(from, Math.min(to, n));// sublist
                res.add(sl.toArray(aagen(componentType)));
            } // for
        
            return res;
        }

        /**
         * 从一个向量里拆出 双精度对象数组
         * 
         * @param seq 向量对象
         * @return 双精度对象数组
         */
        static Double[] unboxed(final Seq<?> seq) {

            final Object[] o = seq == null ? null : seq.data();
            if (o instanceof Double[]) { // 双精度数组
                return (Double[]) seq.data();
            } else if (o instanceof Number[]) { // 数字类型数组
                final var nn = (Number[]) seq.data();
                final var dd = new Double[seq.size()];
                for (int i = 0; i < dd.length; i++) {
                    dd[i] = nn[i].doubleValue();
                }
                return dd;
            } else if (o instanceof String[]) { // 字符串类型
                return Arrays.stream(seq.data()).map(s -> {
                    Double d = null;
                    final var line = s + "";
                    if (line.matches("[.\\d]+"))
                        try {
                            d = Double.parseDouble(line);
                        } catch (Exception e) {
                            e.printStackTrace();
                        } // try
                    return d == null ? 0d : d;
                }).toArray(Double[]::new);
            } else { // 其他的数据对象
                return new Double[] {};
            } // if
        }

        /**
         * 多维数组的 数据读取
         * 
         * @param <T>  多维数组元素的类型
         * @param oo   多维数组对象
         * @param path 维度索引
         * @return path 所标注的数据。
         */
        @SuppressWarnings("unchecked")
        static <T> T read(final T[] oo, final int... path) {
        
            T[] objects = oo; // 单层数组节点
            for (int i = 0; i < path.length - 1; i++) { // 逐层下潜的获取得到单层数组节点
                int j = path[i];
                if (objects[j] != null && objects[j].getClass().isArray()) {
                    objects = (T[]) objects[j];
                } else {
                    return null;
                } // if
            } // for
        
            final int j = path[path.length - 1]; // 提取最后一层数据索引
        
            return j < objects.length ? objects[j] : null;
        }

        /**
         * 多维数组的 数据读取
         * 
         * @param obj  多维数组对象
         * @param path 维度索引
         * @return path 所标注的数据。
         */
        static Object read(final Object obj, final int... path) {

            if (obj == null)
                return null;

            if (obj instanceof Object[]) {
                return read((Object[]) obj, path);
            } else {
                System.err.println("不能为非数组对象做write操作");
                return null;
            } // if
        }

        /**
         * 多维数组的 数据写入 <br>
         * 把值指定的值 value 设置到 oo中 采用 多级索引序列 path 所指定的位置<br>
         * 
         * @param <T>   多维数组元素的类型
         * @param oo    多维数组结构，非多维数组不予写入
         * @param value 多维数组结构
         * @param path  多级索引序列的路径
         */
        static <T> void write(final T[] oo, final T value, final int... path) {
        
            final var writer = distributor(oo, value); // 值分发器(写入器)
        
            writer.accept(path); // 把 value 分发到 indexes
        }

        /**
         * 多维数组的 数据写入 把值指定的值 value <br>
         * 设置到 oo中 采用 多级索引序列 path 所指定的位置<br>
         * 
         * @param obj   待进行多维 索引路径访问的 对象，非多维数组不予写入
         * @param value 多维数组结构
         * @param path  多级索引序列的路径
         */
        static void write(final Object obj, final Object value, final int... path) {

            if (obj instanceof Object[]) {
                write((Object[]) obj, value, path);
            } else {
                System.err.println("不能为非数组对象做write操作");
            } // if
        }

        /**
         * 多维数组的指定维度的 数据修改器 (path位置上写入某个值)
         * 
         * @param <T>  多维数组元素的类型
         * @param oo   多维数组
         * @param path 多级索引序列
         * @return 维度索引设置器 value->{}
         */
        @SuppressWarnings("unchecked")
        static <T> Consumer<T> modifier(final T[] oo, final int... path) {
        
            return value -> {
        
                T[] objects = oo; // 单层数组节点。
                for (int i = 0; i < path.length - 1; i++) { // 逐层下潜的获取得到单层数组节点
                    int j = path[i];
                    if (objects[j] != null && objects[j].getClass().isArray()) {
                        objects = (T[]) objects[j];
                    } else {
                        System.err.println("索引下潜时遇到空值或是非数组类型对象,无法触及到单层数组节点");
                        return;
                    } // if
                } // for
        
                final int j = path[path.length - 1]; // 提取 单层数组节点种的数据值
        
                if (j >= objects.length) {// 索引坐标大于数组长度
                    final var p = Arrays.stream(path).mapToObj(e -> e + "").collect(Collectors.joining(","));
                    System.err.println("in [" + p + "], 下标索引超过" + j + "数组长度空间范围 :" + objects.length + ",不予设置");
                    return;
                } // if
        
                if (objects[j] instanceof Object[]) {// 为高纬进行赋值
                    if (value == null || value.getClass().isArray()) { // 高维数组的值只能是数组
                        objects[j] = value; // 数组类型的值的赋值
                    } else {
                        System.err.println(Arrays.stream(path).mapToObj(e -> e + "").collect(Collectors.joining(","))
                                + " 所标定的元素是一个数组,赋值元素必须为数组类型");
                    } // if
                } else {
                    objects[j] = value;
                } // if
        
            }; // lambda 表达式 : value ->
        }

        /**
         * 多维数组的 值分发器(把一个值投递到,或是写入某个位置上)
         * 
         * @param <T>   多维数组元素的类型
         * @param oo    多维数组
         * @param value 设置的值
         * @return 维度索引设置器 path->{}
         */
        @SuppressWarnings("unchecked")
        static <T> Consumer<int[]> distributor(final T[] oo, final T value) {

            return path -> {

                T[] objects = oo; // 单层数组节点。
                for (int i = 0; i < path.length - 1; i++) { // 逐层下潜的获取得到单层数组节点
                    int j = path[i];
                    if (objects[j] != null && objects[j].getClass().isArray()) { // 对于数组类型进行深度遍历。
                        objects = (T[]) objects[j];
                    } else {
                        System.err.println("索引下潜时遇到空值或是非数组类型对象,无法触及到单层数组节点");
                        return;
                    } // if
                } // for

                final int j = path[path.length - 1]; // 提取 单层数组节点种的数据值

                if (j >= objects.length) {// 索引坐标大于数组长度
                    final var p = Arrays.stream(path).mapToObj(e -> e + "").collect(Collectors.joining(","));
                    System.err.println("in [" + p + "], 下标索引超过" + j + "数组长度空间范围 :" + objects.length + ",不予设置");
                    return;
                } // if

                if (objects[j] instanceof Object[]) {// 为高纬进行赋值
                    if (value == null || value.getClass().isArray()) { // 高维数组的值只能是数组
                        objects[j] = value; // 数组类型的值的赋值
                    } else {
                        System.err.println(Arrays.stream(path).mapToObj(e -> e + "").collect(Collectors.joining(","))
                                + " 所标定的元素是一个数组,赋值元素必须为数组类型");
                    } // if
                } else {
                    objects[j] = value;
                } // if

            }; // lambda 表达式 : path ->
        }

        /**
         * 数组构建器 Array Generator
         * 
         * @param <T>           元素类型
         * @param componentType 数组元素的类型类
         * @return IntFunction 根据尺寸大小生成一维数组的函数,n->T[]
         */
        @SuppressWarnings("unchecked")
        static <T> IntFunction<T[]> aagen(final Class<T> componentType) {

            return n -> (T[]) Array.newInstance(componentType, n);
        }

        /**
         * 获取的ll中元素的类型(第一个元素的类型)
         * 
         * @param <T> 列表的元素类型
         * @param ll  t元素的列表
         * @return ll中元素的类型
         */
        static <T> Class<T> componentType(final Collection<T> ll) {

            @SuppressWarnings("unchecked")
            final var componentType = ll.stream().filter(Objects::nonNull).findFirst().map(e -> (Class<T>) e.getClass())
                    .orElse((Class<T>) Object.class);// 元组鞍的的类型
            return componentType;
        }

        /**
         * 获得cells数组中的元素的数据类型。 如果cells中的所有元素都是null,返回Object.class;
         * 
         * @param <U>   cells数组中的元素的数据类型。
         * @param cells 数据矩阵<br>
         *              defaultClass 当cells 全为空返回的默认类型:Object.class
         * @return cells 元素类型
         */
        @SuppressWarnings("unchecked")
        static <U> Class<U> getGenericClass(final U[][] cells) {
        
            return getGenericClass(cells, (Class<U>) Object.class);
        }

        /**
         * 获得cells数组中的元素的数据类型。 如果cells中的所有元素都是null,返回Object.class;
         * 
         * @param <U>          cells数组中的元素的数据类型。
         * @param cells        数据矩阵
         * @param defaultClass 当cells 全为空返回的默认类型。
         * @return cells 元素类型
         */
        @SuppressWarnings("unchecked")
        static <U> Class<U> getGenericClass(final U[][] cells, final Class<U> defaultClass) {
        
            Class<U> uclass = (Class<U>) defaultClass;
            if (cells == null) return uclass;
            final List<Class<?>> ll = Arrays.stream(cells).flatMap(Arrays::stream).filter(Objects::nonNull)
                    .map((Function<U, ? extends Class<?>>) U::getClass).distinct().collect(Collectors.toList());
            if (ll.size() == 1) {
                uclass = (Class<U>) ll.get(0);
            } else {
                uclass = (Class<U>) Object.class;
            }
        
            return uclass;
        }

        /**
         * 对data进行按照索引位置进行拆分<br>
         * <br>
         * 
         * @param <U>       数组元素类型
         * @param data      待分割的元数据
         * @param positions 大于0的整数列表,表示切分的位点, 即切分索引位置<br>
         *                  切分索引位置（区间结尾索引exclusive,所以需要的是大约0的整数） 序列,<br>
         *                  对于超出过data.length则视为数组的最大长度,<br>
         *                  剔除超过数组长度范围所分割的区间。<br>
         *                  - 比如： [0,1,2,3],按照 {2,5,6}进行切分,定义的区间为:<br>
         *                  [0,2),[2,5),[5,6),由于[2,5)区间跨越了 data的长度,<br>
         *                  所以给他矫正为[2,3),[5,6) 区间给予剔除。<br>
         *                  结果返回 [0,1],[2,3]。<br>
         *                  - 比如：[0,1,2,3],按照[ 2 ] 进行切分,定义了区间 [0,2),[2,4),<br>
         *                  即 定义区间的时候，会自动 补填 0,和 数组常常作为分割点。<br>
         *                  即对于一个长度为4的数组来说,切分简化序列 [2]相当于 [0,2,4]的 切分完整序列。
         * @return 分割片段
         */
        static <U> List<U[]> split(final U[] data, final Integer... positions) {

            final var segments = new LinkedList<U[]>();// 分解片段
            final var pp = Stream.of(positions).sorted().collect(
                    Collector.of((Supplier<LinkedList<Integer>>) LinkedList::new, LinkedList::add, (aa, bb) -> {
                        aa.addAll(bb);
                        return aa;
                    }));// 分割点序列

            if (pp.size() < 1) { // 当切分位点小于1时候，默认不予切分 直接放回 原数据
                segments.add(data);
            } else {
                int start = 0;// 非法切分位点(exclusive),有效切分位点必须 >0
                if (pp.get(0) == 0)
                    pp.removeFirst(); // 注意此时由于移除到了列表元素，列表长度改变了所以需要重新判断列表长度。
                // pp.size() <1 表示 positions中只包含了一个节点，一个做了start，另一个就默认为data.length.
                if (pp.size() < 1 || pp.getLast() < data.length)
                    pp.addLast(data.length);// 补充位置节点（结束节点）为数据末端
                for (final var p : pp) {
                    final var flag = p > data.length;
                    segments.add(Arrays.copyOfRange(data, start, flag ? data.length : p));// 复制
                    if (flag)
                        break;
                    start = p;// 重新设置开始点
                } // for
            } // if

            return segments;
        }

        /**
         * 生成数据矩阵：to Array Row order
         * 
         * @param <T>  矩阵的元素类型
         * @param <U>  Seq的具体实现类型
         * @param rows Seq的后裔类型的元素构成的 列表
         * @return 行顺序构成的数组 rows.count x T[].length
         */
        static <T, U extends Seq<T>> T[][] toArrayR(final Stream<U> rows) {

            return rows.map(Seq::data).collect(Range.aaclc(e -> e));
        }

        /**
         * 生成数据矩阵: to Array Row order
         * 
         * @param <T>    矩阵的元素类型
         * @param <U>    Seq的具体实现类型，本质是T[]的数组
         * @param <R>    结果类型
         * @param rows   TVec的后裔类型的元素构成的 列表
         * @param mapper 矩阵映射函数 ：行顺序构成的数组 rows.count x T[].length -> r
         * @return R 类型的结果
         */
        static <T, U extends Seq<T>, R> R toArrayR(final Stream<U> rows, final Function<T[][], R> mapper) {

            return mapper.apply(toArrayR(rows));
        }

        /**
         * 生成数据矩阵: to Array Column order
         * 
         * @param <T>     矩阵的元素类型
         * @param <U>     TVec的的具体元素类型,
         * @param columns TVec的后裔类型的元素构成的 列表
         * @return 列顺序构成的数组 columns.count x T[].length
         */
        static <T, U extends Seq<T>> T[][] toArrayC(final Stream<U> columns) {

            return columns.map(Seq::data).collect(Range.aaclc(Seq::transpose));
        }

        /**
         * 生成数据矩阵: : to Array Column order
         * 
         * @param <T>     矩阵的元素类型
         * @param <U>     Seq的的具体元素类型,
         * @param <R>     结果类型
         * @param columns TVec的后裔类型的元素构成的 列表
         * @param mapper  矩阵映射函数 ：行顺序构成的数组 columns.count x T[].length -> r
         * @return DataMatrix &lgt; T &gt; 维度为 size|5 x n
         */
        static <T, U extends Seq<T>, R> R toArrayC(final Stream<U> columns, final Function<T[][], R> mapper) {

            return mapper.apply(toArrayC(columns));
        }

        /**
         * 矩阵转置
         * 
         * @param <U>   元素类型
         * @param cells 数据矩阵
         * @return U[][]
         */
        @SuppressWarnings("unchecked")
        static <U> U[][] transpose(final U[][] cells) {
        
            if (cells == null || cells[0] == null) return null;
            
            final int m = cells.length;
            final int n = cells[0].length;
            var u = getGenericClass(cells);
            if (u == null) u = (Class<U>) Object.class;
            final U[][] cc = (U[][]) Array.newInstance(u, n, m);
            for (int i = 0; i < cells.length; i++) {
                for (int j = 0; j < cells[0].length; j++) {
                    cc[j][i] = cells[i][j];
                } // j
            } // i
        
            return cc;
        }

        /**
         * 生成数据矩阵
         * 
         * @param <T>  矩阵的元素类型
         * @param <U>  Seq的的具体元素类型,
         * @param rows Seq的后裔类型的元素构成的 列表
         * @return DataMatrix &lgt; T &gt; 维度为 size|5 x n
         */
        static <T, U extends Seq<T>> DataMatrix<T> matrix_rows(final Stream<U> rows) {
        
            return DataMatrix.of_rows(rows.map(Seq::data));// 把TVec视为列向量来 构造矩阵
        }

        /**
         * 生成数据矩阵
         * 
         * @param <T>     矩阵的元素类型
         * @param <U>     Seq的的具体元素类型,
         * @param columns Seq的后裔类型的元素构成的 列表
         * @return DataMatrix &lgt; T &gt; 维度为 size|5 x n
         */
        static <T, U extends Seq<T>> DataMatrix<T> matrix_columns(final Stream<U> columns) {

            return DataMatrix.of3(columns.map(Seq::data));// 把TVec视为列向量来 构造矩阵
        }

        /**
         * 改变向量(数组)形状:变成多维数组,或者说不只有一维的数组 <br>
         * 当dims的长度小于1的时候，我们将拷贝一个data（向量数据）作为返回结果。<br>
         * 即：Arrays.copyOf(data, dims.length<1?this.size():dims[0]); <br>
         * 核心函数<br>
         * <p>
         * 用法示例: <br>
         * final var tt = (Double[][][])NVec.of(1,2,3,4,5,6,7,8).reshape(2,2,2); <br>
         * 会产生结构: <br>
         * A            B <br>
         * [1.0, 2.0] [3.0, 4.0] <br>
         * [5.0, 6.0] [7.0, 8.0] <br>
         *
         * @param data 源数据
         * @param dims 维度空间长度(大于0的整数)的序列值,第一维度,第二维度,...,第n维
         * @return 新的数组对象, 重新结构后的对象结构
         */
        static <T> Object[] RESHAPE(final T[] data, final Integer... dims) {

            if (data == null) return null;

            final var size = data.length; // 数组数据长度
            final var clazz = data.getClass().getComponentType(); // 元素数据类型
            final Function<int[], Object> newarr = (_dims) -> Array.newInstance(clazz, _dims); // 数组构建函数

            if (dims.length <= 1) { // 维度为1个维度直接返回源数据，即不予变形
                return Arrays.copyOf(data, dims.length < 1 ? size : dims[0]);
            }

            final var diminfo = NVec.of(dims);// 维度空间
            final var volumeinfo = diminfo.bigtail(); // 去除第一索引后剩余的其他维度,即子空间(大小)信息
            for (int i = 0; i < volumeinfo.size() - 1; i++) { // 计算各个子空间的容量大小
                volumeinfo.set(i, NVec.of(diminfo.cuts_picker(i + 1).apply(1)) // 提取后半部分的乘积
                        .product());// 计算每个索引 所包含的 容量空间
            }

            final var volumes = NVec.of(volumeinfo);// 空间的各个维度的长度向量
            final var oo = (Object[]) newarr.apply(NVec.of(dims).ints());// 创建一个多维数组
            final var emptyflag = size <= 0; // 是否为空的标志位
            Range.cph(NVec.of(dims)).forEach(index -> {
                final var i = (int) (index.bighead().dot(volumes) + index.last()); // 下标索引
                Seq.write(oo, emptyflag ? null : data[i % size], index.ints());
            });

            return oo;
        }

        /**
         * 改变向量(数组)形状:变成多维数组,数据变形器
         *
         * @param <X>     数据函数类型占位
         * @param <T>     数组元素类型信息
         * @param <U>     结果类型
         * @param xmapper 结果变换函数,[x:高维数组,不只有一维的数组]->u
         * @param dims 维度空间长度(大于0的整数)的序列值,第一维度,第二维度,...,第n维
         * @return T到U的数据归集器
         */
        @SuppressWarnings("unchecked")
        static <X, T, U> Collector<T, ?, U> reshapeclc(final Function<X, U> xmapper, final Integer... dims) {

            return Range.aaclc(data -> xmapper.apply((X) Seq.RESHAPE(data, dims)));
        }

        /**
         * 把对象转换成Seq序列
         *
         * @param obj 对象数据,如果 obj 本身就是一个SEQ类型,返回一个复制品
         * @return 序列类型的数据
         */
        static Seq<Object> SEQ(final Object obj) {

            return SEQ(obj, false);
        }

        /**
         * 把对象转换成Seq序列 <br>
         * 注意：SEQ 会把单个对象转换成一个只有一个元素的Seq，例如 obj会转换成 [obj] 给予返回
         *
         * @param obj 对象数据,如果 obj 本身就是一个SEQ类型,返回一个复制品
         * @param recursive 是否对子元素进行递归处理
         * @return 序列类型的对象
         */
        @SuppressWarnings("unchecked")
        static Seq<Object> SEQ(final Object obj, final boolean recursive) {

            final Function<Object[], Object[]> array_clone = (oo) -> {
                final var aa = new Object[oo.length];
                System.arraycopy(oo, 0, aa, 0, oo.length);
                return aa;
            };

            final var optional = Optional.ofNullable(obj).map(o -> { // 使用 Optional 实现一个简单的模式匹配
                if (o instanceof Seq) { // Seq 类型直接返回
                    return array_clone.apply(((Seq<Object>) o).data());
                } else if (obj.getClass().isArray()) { // 数组类型转换后返回
                    final var clazz = obj.getClass().getComponentType(); // 获取元素类型
                    return Optional.ofNullable(clazz).map(c->{ // 采用 Optional 代替模式识别,对8大基础类型给予分别处理
                        if(c.equals(int.class)) {
                            return Arrays.stream((int[])o).boxed().toArray();
                        }else if(c.equals(long.class)) {
                            return Arrays.stream((long[])o).boxed().toArray();
                        }else if(c.equals(double.class)) {
                            return Arrays.stream((double[])o).boxed().toArray();
                        }else if(c.equals(char.class)) {
                            final var oo = (char[])o; // 强制转化为数组类型
                            return Stream.iterate(0, i->i+1).limit(oo.length).map(i->oo[i]).map(Character::valueOf).toArray();
                        }else if(c.equals(float.class)) {
                            final var oo = (float[])o; // 强制转化为数组类型
                            return Stream.iterate(0, i->i+1).limit(oo.length).map(i->oo[i]).map(Float::valueOf).toArray();
                        }else if(c.equals(short.class)) {
                            final var oo = (short[])o; // 强制转化为数组类型
                            return Stream.iterate(0, i->i+1).limit(oo.length).map(i->oo[i]).map(Short::valueOf).toArray();
                        }else if(c.equals(boolean.class)) {
                            final var oo = (boolean[])o; // 强制转化为数组类型
                            return Stream.iterate(0, i->i+1).limit(oo.length).map(i->oo[i]).map(Boolean::valueOf).toArray();
                        }else if(c.equals(byte.class)) {
                            final var oo = (byte[])o; // 强制转化为数组类型
                            return Stream.iterate(0, i->i+1).limit(oo.length).map(i->oo[i]).map(Byte::valueOf).toArray();
                        }else { // 其他对象类型
                            return array_clone.apply(((Object[]) o));
                        }//if
                    }).orElse(null); // Optional
                } else { // 其他类型转换成只含有一个元素的 序列
                    return new Object[]{o};
                } // if
            });// optional

            final Seq<Object> seq = () -> optional.map(dd -> { // Seq 匿名类的实现
                if (recursive) for (int i = 0; i < dd.length; i++) { // 递归进行数据处理
                    if (dd[i] == null || (!dd[i].getClass().isArray() && (!(dd[i] instanceof Seq)))) continue;
                    dd[i] = SEQ(dd[i], true);
                }// if
                return dd;
            }).orElse(null); // seq

            return seq;
        }
    }
    
    /**
     * T 类型的向量,即 长度为n的元组 <br> 
     * <br>
     * 向量用来表示 点概念:小则无内的意思:<br>
     * 即它的主要作用就是 通过累加组合(结构化)的方式 形成 其他的 更富有实际意义  的 实例概念(对象概念)。<br>
     * 所以向量 是一个 (原材料概念), 素材概念, 是用于 构成更高级的概念 的 概念 即 单元概念 或是 原子概念  <br>
     * 
     * @author gbench
     *
     * @param <T> 向量的元素的类型
     * @param <SELF> 本身类型：当前类的实际类型，这是一种泛型化实现的向前兼容的设计（技巧）
     */
    public static abstract class TVec<T, SELF> implements Seq<T> {
        
        /**
         * 构造函数
         * @param data 源数据
         */
        public TVec(final T[] data){
            
            this.data = data;
        }
        
        /**
         * 核心函数<br>
         * 根据元素数组构建一个对象实例
         * @param tt 元素数组
         * @return SELF 类型的复制实例
         */
        public abstract SELF build(final T[] tt);

        /**
         * 返回向量数据:直接返回实例数据 引用。
         * 
         * @return 向量数据
         */
        @Override
        public T[] data() {
            
            return this.data;
        }

        /**
         * 返回当前对象本身。这是泛型，向前兼容的设计实现。
         * @return 返回当前对象本身 即 this
         */
        @SuppressWarnings("unchecked")
        public SELF self() {
            
            return (SELF)this;
        }

        /**
         * 提取去除了首位元素后的其余元素序列
         * @return 除了首位元素后的其余元素序列的 SELF 对象
         */
        public SELF cdrX() {
            
            return this.build(this.cdr());
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.iat(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         * 
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public SELF iat(final int... indexes) {

            final var box = new Integer[indexes.length]; // box indexes
            for (int i = 0; i < indexes.length; i++)
                box[i] = indexes[i];
            return this.at(box);
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.at(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         * 
         * @param rng 索引编号范围,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public SELF at(final Range rng) {

            return this.at(rng.intA2());
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.at(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         * 
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public SELF at(final Number... indexes) {

            final var n = this.size();
            final var tt = Arrays.stream(indexes).map(Number::intValue).map(i -> i < n ? this.data[i] : null)
                    .collect(Range.aaclc(e -> e));
            return (SELF) this.build(tt);
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.at(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         * 
         * @param <U>     nums的数值类型
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public <U extends Number> SELF at(final TVec<U, ?> indexes) {

            return this.at(indexes.toArray());
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         * 
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public SELF igets(final int... indexes) {

            final var box = new Integer[indexes.length]; // box indexes
            for (int i = 0; i < indexes.length; i++)
                box[i] = indexes[i];
            return this.filter((id, x) -> eq(box).test(id, x));
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         * 
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public SELF gets(final Number... indexes) {

            return this.filter((id, x) -> eq(indexes).test(id, x));
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         * 
         * @param rng 索引编号序列的范围,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public SELF gets(final Range rng) {

            return this.gets(rng.intA2());
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         * 
         * @param <U>     nums的数值类型
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public <U extends Number> SELF gets(final Seq<U> indexes) {

            return this.gets(indexes.toArray());
        }

        /**
         * 提取不包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[1.0, 2.0, 3.0, 5.0, 7.0, 8.0, 9.0, 10.0] <br>
         * 
         * @param indexes 索引编号序列,编号从 0开始
         * @return 不包含 indexes 所标定的元素所指定的NVec
         */
        public SELF gets2(final Number... indexes) {

            return this.filter((id, x) -> neq(indexes).test(id, x));
        }

        /**
         * 提取不包含 indexes所指定的数据元素 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[1.0, 2.0, 3.0, 5.0, 7.0, 8.0, 9.0, 10.0] <br>
         * 
         * @param indexes 索引编号序列,编号从 0开始
         * @return 不包含 indexes 所标定的元素所指定的NVec
         */
        public <U extends Number> SELF gets2(final Seq<U> indexes) {

            return this.gets2(indexes.data());
        }

        /**
         * 设置第i个元素的值
         * 
         * @param i     设置的位置，从0开始
         * @param value 设置的值
         * @return 对象本身以实现链式编程
         */
        public SELF set(final int i, T value) {

            return this.set(i, e -> value);
        }

        /**
         * 设置第i个元素的值
         * 
         * @param i       设置的位置，从0开始
         * @param valueer 设置的值的计算函数:t->t
         * @return 对象本身以实现链式编程
         */
        public SELF set(final int i, Function<T, T> valueer) {

            this.data[i] = valueer.apply(this.get(i));

            return this.self();
        }

        /**
         * 调换 i,j 两个位置的元素
         * 
         * @param i 大于等于0的整数,位置索引从0开始
         * @param j 大于等于0的整数,位置索引从0开始
         * @return SELF对象自身便于实现链式编程
         */
        public SELF swap(final int i, final int j) {

            final var t = this.mget(i); // 临时变量
            this.data[i] = this.data[j];
            this.data[j] = t;

            return this.self();
        }

        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值<br>
         * vec.evaluate((i,v)->vec.set(i,v),1,23);<br>
         * 
         * @param callback 回调函数
         * @param oo       (索引,值) 的 序列 :索引1,值1,索引2,值2,...<br>
         *                 注意 索引是为Integer类型,Value 是T类型。oo 需要在传入的时候 保证各自类型的正确性
         * @return NVec 自身以便实现链式编程
         */
        @SuppressWarnings("unchecked")
        public SELF evaluate(final BiConsumer<Integer, T> callback, final Object... oo) {

            final var size = oo.length;
            for (var i = 0; i < size - 1; i += 2)
                callback.accept((Integer) oo[i], (T) oo[i + 1]);

            return self();
        }

        /**
         * 对data进行按照索引位置进行拆分<br>
         * <br>
         * 
         * @param positions 大于0的整数列表,表示切分的位点, 即切分索引位置<br>
         *                  切分索引位置（区间结尾索引exclusive,所以需要的是大约0的整数） 序列,<br>
         *                  对于超出过data.length则视为数组的最大长度,<br>
         *                  剔除超过数组长度范围所分割的区间。<br>
         *                  - 比如： [0,1,2,3],按照 {2,5,6}进行切分,定义的区间为:<br>
         *                  [0,2),[2,5),[5,6),由于[2,5)区间跨越了 data的长度,<br>
         *                  所以给他矫正为[2,3),[5,6) 区间给予剔除。<br>
         *                  结果返回 [0,1],[2,3]。<br>
         *                  - 比如：[0,1,2,3],按照[ 2 ] 进行切分,定义了区间 [0,2),[2,4),<br>
         *                  即 定义区间的时候，会自动 补填 0,和 数组常常作为分割点。<br>
         *                  即对于一个长度为4的数组来说,切分简化序列 [2]相当于 [0,2,4]的 切分完整序列。
         * @return 分割片段
         */
        public List<SELF> split(final Integer... positions) {

            final var data = data();
            return Seq.split(data, positions).stream().map(this::build).collect(Collectors.toList());
        }

        /**
         * 复制，克隆一个当前对象的实例
         * 
         * @return SELF的复制实例
         */
        public SELF duplicate() {
            
            return this.build(this.data);
        }

        /**
         * 构造一组复制品(复制n次)
         *
         * @param n 衍生（复制）的规模次数
         * @return SELF 的数据流 长度为 n
         */
        public Stream<SELF> replicateS(final int n) {

            return this.duplicateS(n, (i, x) -> x);
        }

        /**
         * 构造一个复制品
         * 
         * @param self_creator 派生类构建器
         * @return 派生类 SELF
         */
        public SELF duplicate(final Function<TVec<T, SELF>, SELF> self_creator) {

            return self_creator.apply(this);
        }

        /**
         * 构造一组复制品
         *
         * @param <X>      结果类型
         * @param n        衍生（复制）的规模次数,大于0的整数
         * @param derivate 衍生器
         * @return X 的数据路
         */
        @SuppressWarnings("unchecked")
        public <X> Stream<X> duplicateS2(final int n, final BiFunction<Integer, T[], X> derivate) {

            return Stream.iterate(0, i -> i < n, i -> i + 1)
                    .map(i -> derivate.apply(i, ((TVec<T, ?>) this.duplicate()).data()));
        }

        /**
         * 构造一组复制品
         *
         * @param <X>      结果类型
         * @param n        衍生（复制）的规模次数,大于0的整数
         * @param derivate 衍生器
         * @return X 的数据路
         */
        public <X> Stream<X> duplicateS(final int n, final BiFunction<Integer, SELF, X> derivate) {

            return Stream.iterate(0, i -> i < n, i -> i + 1).map(i -> derivate.apply(i, this.duplicate()));
        }

        /**
         * 连接 自身与另一个 SELF结构形成一个 SELF对象 <br>
         * 例如 [1,2].concat([3,4],[5,6]) 会生成一个 [1,2,3,4,5,6]<br>
         * 
         * @param ss 另一组SELF的结构的对象数组
         * @return 新生成的self结构的对象.
         */
        @SafeVarargs
        @SuppressWarnings("unchecked")
        public final SELF concat(final SELF... ss) {
            
            final var t2 = ((TVec<T, SELF>[]) ss);
            final var componentType = this.getComponentType();
            final var tt = Stream.concat(Stream.of(this), Stream.of(t2)).flatMap(TVec::stream)
                    .toArray(n -> (T[]) Array.newInstance(componentType, n));
            return this.build(tt);
        }

        /**
         * 构造一个位于 from 与 to 之间的拷贝
         * 
         * @param from 拷贝范围的开始位置索引,从0开始, 包含inclusive
         * @param to   拷贝范围的结束位置索引, 不包含exclusive.(to 所索引可以放置于与数组范围以外)。
         *             比如：[1,2].copyOfRange(1, 3)将返回一个 [2,null]的结构
         * @return SELF 对象
         */
        public SELF copyOfRange(final int from, final int to) {

            final var tt = Arrays.copyOfRange(this.data, from, to);
            return this.build(tt);
        }

        /**
         * 对数据元素采用了过滤谓词进行过滤，生成一个过滤得出的子对象
         * 
         * @param filterb 过滤标记向量<br>
         *                boolean类型的数过滤序列,true 返回,false 滤除，灵感来自于R的语言的下标索引<br>
         *                当filterb为null或是长度小于1时候，默认为返回所数据元素.<br>
         *                filterb数据元素会被循环填充以保证可以与SELF一一对应.<br>
         * @return SELF 数据对象
         */
        public SELF filter(final Boolean... filterb) {

            final var flags = (filterb == null || filterb.length < 1) ? new Boolean[] { false } : filterb; // 过滤标志向量
            final var n = flags.length;
            return this.filter((i, t) -> flags[i.intValue() % n]);
        }

        /**
         * 对数据元素采用了过滤谓词进行过滤，生成一个过滤得出的子对象
         * 
         * @param filterb 过滤标记向量<br>
         *                boolean类型的数过滤序列,true 返回,false 滤除，灵感来自于R的语言的下标索引<br>
         *                当filterb为null或是长度小于1时候，默认为返回所数据元素.<br>
         *                filterb数据元素会被循环填充以保证可以与SELF一一对应.<br>
         * @return SELF 数据对象
         */
        public SELF filter(final XVec<Boolean> filterb) {

            return this.filter(filterb.data);
        }

        /**
         * 对数据元素采用了过滤谓词进行过滤，生成一个过滤得出的子对象
         * 
         * @param predicate 过滤谓词：[t]->true
         * @return SELF 数据对象
         */
        @SuppressWarnings("unchecked")
        public SELF filter(final Predicate<T> predicate) {

            final var componentType = this.getComponentType();
            final var dd = this.stream().filter(predicate).toArray(n -> (T[]) Array.newInstance(componentType, n));
            return (SELF) this.build(dd);
        }

        /**
         * 对数据元素采用了过滤谓词进行过滤，生成一个过滤得出的子对象
         * 
         * @param bipredicate 过滤谓词：[id,t]->true,id 从0开始
         * @return SELF 数据对象
         */
        @SuppressWarnings("unchecked")
        public SELF filter(final BiPredicate<Long, T> bipredicate) {

            final var al = new AtomicLong(0L);
            final var componentType = this.getComponentType();
            final var dd = this.stream().filter(x -> bipredicate.test(al.getAndIncrement(), x))
                    .toArray(n -> (T[]) Array.newInstance(componentType, n));
            return (SELF) this.build(dd);
        }

        /**
         * 后缀S表示是 返回的结果是 Stream类型 <br>
         * split 的 别名 对data进行按照索引位置进行拆分<br>
         * <br>
         * 
         * @param positions 大于0的整数列表,表示切分的位点, 即切分索引位置<br>
         *                  切分索引位置（区间结尾索引exclusive,所以需要的是大约0的整数） 序列,<br>
         *                  对于超出过data.length则视为数组的最大长度,<br>
         *                  剔除超过数组长度范围所分割的区间。<br>
         *                  - 比如： [0,1,2,3],按照 {2,5,6}进行切分,定义的区间为:<br>
         *                  [0,2),[2,5),[5,6),由于[2,5)区间跨越了 data的长度,<br>
         *                  所以给他矫正为[2,3),[5,6) 区间给予剔除。<br>
         *                  结果返回 [0,1],[2,3]。<br>
         *                  - 比如：[0,1,2,3],按照[ 2 ] 进行切分,定义了区间 [0,2),[2,4),<br>
         *                  即 定义区间的时候，会自动 补填 0,和 数组常常作为分割点。<br>
         *                  即对于一个长度为4的数组来说,切分简化序列 [2]相当于 [0,2,4]的 切分完整序列。
         * @return 分割片段的流
         */
        public Stream<? extends SELF> splitS(final Integer... positions) {

            return Seq.split(data, positions).stream().map(this::build);
        }

        /**
         * 突变出一个新的对象U
         * 
         * @param <U>     新的对象类型
         * @param mutator 突变方法:self->U
         * @return 新的对象U
         */
        public <U> U mutateX(final Function<SELF, U> mutator) {

            return mutator.apply(this.self());
        }

        /**
         * 保持结构不变的内容拷贝/修改，与update的区别就是copy不是修改原数据自身值，只是先生成一个拷贝对象然后修改
         * 
         * @param copyer 内容拷贝算法 : t->t
         * @return 新的SELF对象
         */
        @SuppressWarnings("unchecked")
        public SELF copy(final Function<T, T> copyer) {

            final var tvec = this.duplicate();
            this.foreach((i, t) -> ((TVec<T, SELF>) tvec).set(i, copyer.apply(t)));

            return tvec;
        }

        /**
         * 保持结构不变的内容拷贝/修改，与update的区别就是copy不是修改原数据自身值，只是先生成一个拷贝对象然后修改
         * 
         * @param copyer 内容拷贝算法: (i:元素下标索引从0开始,t:元素数据)->t
         * @return 新的SELF对象
         */
        @SuppressWarnings("unchecked")
        public SELF copy(final BiFunction<Integer, T, T> copyer) {

            final var tvec = this.duplicate();
            this.foreach((i, t) -> ((TVec<T, SELF>) tvec).set(i, copyer.apply(i, t)));

            return tvec;
        }

        /**
         * reverse 的别名函数<br>
         * 生成以元素顺序与当前元素属性相反的 向量。 如 [1,2,3] -> [3,2,1]
         *
         * @return 元素顺序与当前元素属性相反的 新的 向量
         */
        public SELF R() {
            return this.reverse();
        }

        /**
         * reverse 的别名函数<br>
         * 生成以元素顺序与当前元素属性相反的 向量。 如 [1,2,3] -> [3,2,1]
         *
         * @return 元素顺序与当前元素属性相反的 新的 向量
         */
        public SELF rev() {
            return this.reverse();
        }

        /**
         * 生成以元素顺序与当前元素属性相反的 向量。 如 [1,2,3] -> [3,2,1]
         * 
         * @return 元素顺序与当前元素属性相反的 新的 向量
         */
        @SuppressWarnings("unchecked")
        public SELF reverse() {

            final var dd = this.duplicate();// 复制一个对象
            final var data = ((TVec<T, SELF>) dd).data;// 提取数据空间
            final var n = data.length;

            for (int i = 0; i < (n) >>> 2 - 1; i++) {
                T t = data[i];
                data[i] = data[n - i - 1];
                data[n - i - 1] = t;
            } // for

            return dd;
        }

        /**
         * 对元素序列进行排序
         * 
         * @return 排序后的元素向量
         */
        public SELF sorted() {
            
            final T[] tt = this.stream().sorted().collect(Range.aaclc(e -> e)); // 重排数据
            return this.build(tt); // 生成重排的数据实例
        }

        /**
         * 对元素序列进行排序
         * 
         * @param weighter 排序的向量的权重函数 t->num <br>
         *                 即把 t映射成一个可以进行比较的数值权重(weight)而后按照weight进行排序：从小打到大
         * @return 排序后的元素向量
         */
        public SELF sorted(final Function<T, Number> weighter) {
            
            final T[] tt = this.sortedS(weighter).collect(Range.aaclc(e -> e)); // 重排数据
            return this.build(tt); // 生成重排的数据实例
        }

        /**
         * 对元素序列进行排序
         * 
         * @param comparator 元素比较函数 (a,b)-> int,a non-interfering, stateless Comparator
         *                   to be used to compare stream elements
         * @return 排序后的元素向量
         */
        public SELF sorted(final Comparator<? super T> comparator) {
            
            final T[] tt = this.stream().sorted(comparator).collect(Range.aaclc(e -> e)); // 重排数据
            return this.build(tt); // 生成重排的数据实例
        }

        /**
         * 数据随机权重,而后给予重排顺序
         * 
         * @return SELF 的对象实例
         */
        public SELF shuffle() {
            
            return this.shuffle(e -> Math.random());
        }

        /**
         * 一元权重:只计算权重不改变t值,t->wt <br>
         * 先为数据指定权重，而后给予重排顺序
         *
         * @param weighter 排序的向量的权重函数 t->num <br>
         *                 即把 t映射成一个可以进行比较的数值权重(weight)而后按照weight进行排序：从小打到大
         * @return SELF 的对象实例
         */
        public SELF shuffle(final Function<T, Number> weighter) {
            
            final T[] tt = this.shuffleS(Weightable.weightf(weighter)).collect(Range.aaclc(e -> e)); // 重排数据
            return this.build(tt);
        }

        /**
         * 二元变换:可以改变t值 (i,t)->weightable <br>
         * 先为数据指定权重，而后给予重排顺序
         *
         * @param mapper 元素变换器,把T 变换成一个带有权重的 T值 : <br>
         *               (i:索引序号从0开始,t:元素值) -> weightable&lt;t&gt;
         * @return SELF 的对象实例
         */
        public SELF shuffle(final BiFunction<Integer, T, Weightable<T>> mapper) {
            
            final T[] tt = this.shuffleS(mapper).collect(Range.aaclc(e -> e)); // 重排数据
            return this.replace(0, tt.length, tt); // 生成重排的数据实例
        }

        /**
         * 二元变换:可以改变t值 (i,t)->weight <br>
         * 先为数据指定权重，而后给予重排顺序
         *
         * @param weighter 排序的向量的权重函数 (i:索引序号从0开始,t:元素值)->num <br>
         *                 即把 (i,t)映射成一个可以进行比较的数值权重(weight)而后按照weight进行排序：从小打到大
         * @return SELF 的对象实例
         */
        public SELF shuffle2(final BiFunction<Integer, T, Number> weighter) {
            
            return this.shuffle((i, t) -> {
                final var wt = weighter.apply(i, t);
                return Weightable.of(wt == null ? null : wt.doubleValue(), t);
            });
        }

        /**
         * 数据窗口滑动 (sliding Stream)<br>
         * 对一个:1 2 3 4,按照 size:为2,step为1的参数进行滑动的结果。<br>
         * 
         * | size | 每个窗口大小为 size,每次移动的步长为step<br>
         * [1 2]<br>
         * step0:[2 3]<br>
         * - step1:[3 4]<br>
         * - - step2:[4]<br>
         * 返回:[ [1,2], [2,3], [3,4], [4] ]<br>
         * 
         * @param size 滑动的窗口大小
         * @param step 每次移动的步长
         * @return 滑动窗口的列表。
         */
        public Stream<? extends SELF> slidingS(final int size, final int step) {
            
            return this.slidingS(size, step, this::build);
        }

        /**
         * 数据切片
         * 
         * @param sizes 切片尺寸大小,切片尺寸会被循环使用
         * @return 切片集合
         */
        public List<? extends SELF> slice(final int... sizes) {
            
            return this.slice(this::build, sizes);
        }

        /***
         * 生成指定大小的SELF对象 <br>
         *
         * 如果newsize大于当前数据长度 使用null进行进行补填。<br>
         *
         * @param newsize 新的尺寸大小 <br>
         * @return SELF 类型的新的对象结构
         */
        public SELF resize0(final Number newsize) {

            return this.resize(newsize, (T[]) null);
        }

        /***
         * 生成指定大小的SELF对象 <br>
         * 
         * 如果newsize大于当前数据长度 使用自身数据data进行循环补位进行补填。<br>
         * 如果 tt 为null或是长度为0，则不予进行数据填充。 <br>
         * 
         * @param newsize 新的尺寸大小 <br>
         * @return SELF 类型的新的对象结构
         */
        public SELF resize(final Number newsize) {

            return this.resize(newsize, this.data);
        }

        /***
         * 生成指定大小的SELF对象
         * 
         * @param newsize 新的尺寸大小
         * @param tt      如果newsize大于当前数据长度所使用的填充数据，数据采用循环补位进行。<br>
         *                如果 tt 为null或是长度为0，则不予进行数据填充。
         * @return SELF 类型的新的对象结构
         */
        @SafeVarargs
        public final SELF resize(final Number newsize, final T... tt) {

            final var nsz = newsize.intValue(); // NSiZe
            if (nsz < 0) {
                System.err.println("newsize 必须是大于等于0的整数,部分为负数,resize 失败");
                return null;
            }

            final T[] data = Arrays.copyOfRange(this.data, 0, nsz);
            if (tt != null && tt.length > 0) {
                final var n = tt.length;
                final var sz = this.size();
                for (int i = sz; i < nsz; i++) {
                    data[i] = tt[(i - sz) % n];
                } // for 补填数据
            } // if

            return this.build(data);
        }

        /***
         * 生成指定大小的SELF对象
         * 
         * @param newsize 新的尺寸大小
         * @param tvec    待插入的数据
         * @return SELF 类型的新的对象结构
         */
        public final SELF resize(final Number newsize, final TVec<T, ?> tvec) {

            return this.resize(newsize, tvec.data());
        }

        /**
         * 头部添加
         *
         * @param tvec 待插入的数据
         * @return 加入了tvec后的新的数据向量
         */
        public SELF prepend(final TVec<T, ?> tvec) {

            return this.insert(0, tvec);
        }

        /**
         * 尾部追加
         *
         * @param tvec 待插入的数据
         * @return 加入了tvec后的新的数据向量
         */
        public SELF append(final TVec<T, ?> tvec) {

            return this.insert(null, tvec);
        }

        /**
         * 头部添加
         *
         * @param tt 待插入的数据
         * @return 插入了tt后的新的数据向量
         */
        @SafeVarargs
        public final SELF prepend(final T... tt) {

            return this.insert(0, tt);
        }

        /**
         * 尾部追加
         *
         * @param tt 待插入的数据
         * @return 插入了tt后的新的数据向量
         */
        @SafeVarargs
        public final SELF append(final T... tt) {

            return this.insert(0, tt);
        }

        /**
         * 在向量的 pos位置插入数据 tvec
         *
         * @param pos  插入的索引位置从0开始:<br>
         *             当pos为null的时候回视为this.size即在尾部进行插入<br>
         *             当pos大于当前数据长度的时候，插入位置会被自动重定位到当前向量的末尾 <br>
         *             当插入位置小于0的时候，返回 null <br>
         * @param tvec 待插入的数据
         * @return 加入了tvec后的新的数据向量
         */
        public SELF insert(final Number pos, final TVec<T, ?> tvec) {

            return this.replace(pos, pos, tvec == null ? null : tvec.data);
        }

        /**
         * 在向量的 pos位置插入数据 tt
         *
         * @param pos 插入的索引位置从0开始:<br>
         *            当pos为null的时候回视为this.size即在尾部进行插入<br>
         *            当pos大于当前数据长度的时候，插入位置会被自动重定位到当前向量的末尾 <br>
         *            当插入位置小于0的时候，返回 null <br>
         * @param tt  待插入的数据
         * @return 插入了tt后的新的数据向量
         */
        @SuppressWarnings("unchecked")
        public SELF insert(final Number pos, final T... tt) {

            return this.replace(pos, pos, tt);
        }

        /**
         * 使用tev的数值更新自己(不会改变数据长度）
         * 
         * @param seq seq中的数据会被循环使用以匹配SELF的数据长度
         * @return SELF数据对象本身 以实现链式编程
         */
        public SELF update(final Seq<T> seq) {

            final var n = seq.size();
            final var data = seq.data();
            this.update((i, v) -> data[i % n]);
            return this.self();
        }

        /**
         * 带序号的 采样点遍历更新 <br>
         * 通updator遍历访问 NVec中的每个元素。 <br>
         * 遍历的索引序号从0开始 <br>
         * <br>
         *
         * @param updator 二元回调函数 (i:索引号,t:采样点)->t,会使用 updator 的返回值更新当前的i位置的值
         * @return SELF对象本身已方便实现链式编程
         */
        public SELF update(final BiFunction<Integer, T, T> updator) {

            final var ai = new AtomicInteger(0); // 计数器
            this.stream().forEach(d -> {
                final var i = ai.getAndIncrement(); // 获取索引序号
                final var v = updator.apply(i, d); // 索引位置计算
                this.set(i, v); // 用新计算的值更新 i位置的数据
            });// forEach

            return this.self();
        }

        /**
         * 把start,end 之间的数据给予去除
         * start,end 需要时大于等于0的正整数，若为负数 直接  返回null <br>
         * 当start 大于等于 当前长度的时候的，返回一个 当前SELF对象的完整复制品 <br>
         * @param start 开始位置 包含inclusive 从0开始
         * @param end 结束位置 不包含exclusive 从0开始。end 位置需要大于start，如果小于则返回null
         *            如果end为null默认为start+tt.length
         * @return 去除了 start 与 end 之间的数据的 SELF 对象
         */
        public SELF delete(final Number start, final Number end) {
            
            if(start==null|end==null||start.intValue()<0||end.intValue()<0||start.intValue()>=end.intValue())return null;
            final var s = start.intValue(); // 开始位置
            final var e = Math.min(end.intValue(), this.size());// 把end value 调整到 最大为 当前向量长度的结尾末端的位置
            if(s>=this.size()) return this.duplicate(); // 
            final var n = e-s; // 删除数据的长度
            final var data = Arrays.copyOfRange(this.data, 0, this.size()-n);// 拷贝数据总长
            // 把剩余的数据元素给提到前面来。
            if (data.length - s >= 0) System.arraycopy(this.data, s + n, data, s, data.length - s);
            
            return this.build(data);
        }
        
        /**
         * 删除pos位置的元素
         * 
         * @param pos 位置序号从0开始,小于向量长度
         * @return 去除掉pos位置的元素的剩余向量 （新生成）
         */
        public SELF delete(final Number pos) {

            return this.delete(pos, pos.intValue() + 1);
        }
        
        /**
         * delete 函数的别名 <br>
         * 删除pos位置的元素
         * 
         * @param pos 位置序号从0开始,小于向量长度
         * @return 去除掉pos位置的元素的剩余向量 （新生成）
         */
        public SELF remove(final Number pos) {

            return this.delete(pos);
        }

        /**
         * 使用 tvec 中的内容替换掉 start 与 end 之间的数据 <br>
         * 当start为null或是小于0的时候返回null<br>
         * @param start 开始位置 包含 inclusive 从0开始 <br>
         *              start小于0的时候返回null<br>
         *              当start为null时,视为this.size()<br>
         * @param tvec 待插入的数据,当 tt 为null时视为替换一个长度为0的数据序列
         * @return 使用 tvec 中的内容替换掉 start 与 end 之间的数据 后的数据向量（新生成)
         */
        public SELF replace(final Number start,final TVec<T,?> tvec) {

            return this.replace(start, null, tvec == null ? null : tvec.data);
        }

        /**
         * 使用 tt 中的内容替换掉 start 与 end 之间的数据 <br>
         *
         * @param start 开始位置 包含 inclusive 从0开始 <br>
         *              当start小于0的时候返回null<br>
         *              当start为null时,视为this.size()<br>
         * @param end   结束位置 不包含 exclusive 从0开始。end 位置需要大于start，如果小于则返回null<br>
         *              如果end为null默认为start+tt.length
         * @param tt    待插入的数据,当 tt 为null时视为替换一个长度为0的数据序列
         * @return 使用 tt 中的内容替换掉 start 与 end 之间的数据 后的数据向量(新生成)
         */
        @SuppressWarnings("unchecked")
        public SELF replace(final Number start, final Number end, final T... tt) {

            if (start != null && start.intValue() < 0) return null; // 当插入位置小于0的时候，返回 null
            final var insert_data = tt == null ? (T[]) new Object[] {} // 待插入的数据,注意 这里的 new Object[]只是一个占位符，实际上不会进行数据拷贝的。
                : tt; 

            final var _s = start == null ? this.size() : start.intValue(); // 开始位置
            final var s = Math.min(_s, this.size());// 插入位置的调整
            final var _e = end == null ? s + insert_data.length : end.intValue(); // 结束位置
            final var e = Math.min(_e, this.size()); // 结束位置的调整

            final var total_sz = this.size() + insert_data.length - (e - s); // 插入数据后的总的长度，减去 替换掉的数据长度(e-s)
            final var insert_sz = insert_data.length; // 插入数据的长度
            final var data = Arrays.copyOfRange(this.data, 0, total_sz);// 拷贝数据总长
            System.arraycopy(insert_data, 0, data, s, insert_sz); // 在插入开始位置插入数据
            for (int i = s + insert_sz, j = 0; i < total_sz; i++) {
                data[i] = this.data[e + j++];// 把插入结束位置的后面的数据一股脑的拷贝到结果缓存data之中
            }

            return this.build(data);
        }

        /**
         * 使用 tvec 中的内容替换掉 start 与 end 之间的数据 <br>
         *
         * @param start 开始位置 包含 inclusive 从0开始 <br>
         *              start小于0的时候返回null<br>
         *              当start为null时,视为this.size()<br>
         * @param end 结束位置 不包含 exclusive 从0开始。end 位置需要大于start，如果小于则返回null <br>
         *            如果end为null默认为start+tt.length
         * @param tvec 待插入的数据,当 tt 为null时视为替换一个长度为0的数据序列
         * @return 使用 tvec 中的内容替换掉 start 与 end 之间的数据 后的数据向量(新生成)
         */
        public SELF replace(final Number start, final Number end,final TVec<T,?> tvec) {
            
            return this.replace(start, end, tvec == null ? null : tvec.data);
        }
        
        /**
         * 提取大尾巴向量(除了1个小脑袋,其余全都是尾巴)<br>
         * 相当于 tail(size-1)
         * 
         * @return 除掉第一个元素的其他元素
         */
        public SELF bigtail() {
            
            return this.tail(this.size()-1);
        }

        /**
         * 提取尾部向量
         * 
         * @param num 尾部元素的数量,大于等于0的整数,当 num 大于数组长度时,返回全体元素
         * @return 提取尾部的长度为 num 的数据向量
         */
        public SELF tail(final Number num) {
            
            final var n = Math.abs(num.intValue());
            if (this.size() >= n) {
                return this.build(Arrays.copyOfRange(this.data, this.size()-n,this.size()));
            } else {
                return this.build(this.toArray());
            }
        }
        
        /**
         * 提取首部向量
         * 
         * @param num 头前的元素数量,大于等于0的整数,当 num 大于数组长度时,返回全体元素
         * @return 提取首部的长度为 num 的数据向量
         */
        public SELF head(final Number num) {
            
            final var n = Math.abs(num.intValue());
            if(this.size()>=n) {
                return this.build(Arrays.copyOf(this.data, n));
            }else {
                return this.build(this.toArray());
            }
        }

        /**
         * 提取大脑袋向量提取大尾巴向量(除了1个小尾巴,其余全都是大脑袋)<br>
         * 相当于 head(size-1)
         * 
         * @return 除掉最后一个元素的其他元素
         */
        public SELF bighead() {
            
            return this.head(this.size()-1);
        }
        
        /**
         * 采样点遍历 <br>
         * 通cs遍历访问 SELF 中的每个 元素。
         * @param cs 回调函数 t->{}
         * @return SELF对象  对象本身已方便实现链式编程
         */
        public SELF foreach(final Consumer<T> cs) {
            
            this.stream().forEach(cs);
            
            return this.self();
        }
        
        /**
         * 带序号的 采样点遍历 <br>
         * 通cs遍历访问 SELF 中的每个 元素。 <br>
         * 遍历的索引序号从0开始 <br>
         * <br>
         * @param cs 二元回调函数 (i:索引号,t:采样点)->{}
         * @return SELF对象本身已方便实现链式编程
         */
        public SELF foreach(final BiConsumer<Integer,T> cs) {
            
            final var ai = new AtomicInteger(0); // 计数器
            this.stream().forEach(d->cs.accept(ai.getAndIncrement(), d));
            
            return this.self();
        }
        
        /**
         * 求出两个集合的差
         * @param other 另一个 SELF 对象
         * @return 集合差对象
         */
        public SELF diff(final Seq<T> other){
            return this.build(this.diffSeq(other));
        }

        /**
         * 求出两个集合的合并
         *
         * @param other 另一个 SELF 对象
         * @return 集合差对象
         */
        public SELF union(final Seq<T> other) {
            return this.build(this.unionSeq(other));
        }

        /**
         * 求出两个集合的交集
         * @param other 另一个 SELF 对象
         * @return 集合差对象
         */
        public SELF intersect(final Seq<T> other){
            return this.build(this.intersectSeq(other));
        }

        /**
         * 对弈个对象进行散列
         * @return 散列码
         */
        @Override
        public int hashCode() {

            return Arrays.hashCode(this.data);
        }

        /**
         * 判断两个对象是否相等
         * @param obj 另一个对象
         * @return 两个对象是否相等
         */
        @Override
        public boolean equals(final Object obj) {

            if(obj==null)return false;
            if(this==obj)return true;
            if(this.getClass()!=obj.getClass())return false;
            @SuppressWarnings("unchecked")
            final var tvec =((TVec<T,SELF>) obj);
            if(this.getComponentType()!=tvec.getComponentType())return false;

            return Arrays.equals(this.data,tvec.data);
        }
        
        /**
         * 字符串格式化
         * 
         * @return 格式化文本
         */
        @Override
        public String toString() {

            return this.toString(e -> {
                if (e == null) {
                    return "null";
                } else {
                    if (e.getClass().isArray()) {
                        return Arrays.deepToString((Object[]) e);
                    } else {
                        return e.toString();
                    } // if
                } // if
            }); // toString
        }

        /**
         * 字符串格式化
         * 
         * @param formatter 元素格式化器
         * @return 格式化文本
         */
        public String toString(final Function<T, String> formatter) {
            final var line = Arrays.stream(this.data).map(formatter).collect(Collectors.joining(" , "));
            return "[ "+line+" ]";
        }
        
        /**
         * data 向量的数据元素序列
         */
        protected final T[] data;
    }// TVec
    
    /**
     * 
     * XVec 元素为某种类型(X)的 向量,即 长度为n的元组<br>
     * <br>
     * 
     * @author gbench
     *
     * @param <T> 元素类型
     */
    public static class XVec<T> extends TVec<T, XVec<T>> {

        /**
         * 狗啊走函数
         * 
         * @param data 基础数据,T类型的数组，
         */
        public XVec(final T[] data) {

            super(data);
        }

        /**
         * 拷贝构造
         * 
         * @param tvec T类型的 基础向量
         */
        public XVec(final TVec<T, XVec<T>> tvec) {

            super(tvec.data);
        }

        /**
         * 根据元素数组构建一个对象实例
         * 
         * @param tt 元素数组
         * @return SELF 类型的复制实例
         */
        public XVec<T> build(final T[] tt) {
            
            return XVec.OF(tt);
        }

        /**
         * 返回数据形状:依据索引序列所排成各个索引维度长度的数字列表。 <br>
         * 数据形状按照car的元素进行估计核算，注意返回的shapehi估计大小，<br>
         * 即假设XVec元素是均质的,统计类型包括:数组,XVec,Collection三类。 <br>
         * <br>
         * 这里有个有趣的问题，就是 XVec使用期子类NVec作为返回值。主要原因就是 NVec提供数值<br>
         * 计算的能力.可以方便进行维度乘积.比如 x.shape().product() 这种方式来估计 flat后<br>
         * 的空间大小的计算的便捷性.<br>
         * <br>
         * 
         * @return 当前向量的形状[第一维度,第二维度,...]
         */
        public XVec<Integer> shape() {
            
            return this.shape(XVec::new);
        }

        /**
         * 强制类型转换,如果完成 不同类型的之间的变换,请使用 derive2
         * 
         * @param <U>   目标类型类的类型
         * @param clazz 目标类型类
         * @return 变换了内部数据类型的 XVec
         */
        @SuppressWarnings("unchecked")
        public <U> XVec<U> corece(final Class<U> clazz) {

            final var n = this.data.length;
            final U[] aa = (U[]) Array.newInstance(clazz, n);
            for (int i = 0; i < this.data.length; i++)
                aa[i] = (U) (this.data[i]);

            return new XVec<>(aa);
        }

        /**
         * 衍生化出一个 同构对象:向量(数组)级别的变换
         * 
         * @param <U>    目标类型的类型
         * @param mapper 转换到目标类型类的的 映射 方法 : [t]->[u]
         * @return 内部元素类型为U类型的 的 XVec
         */
        public <U> XVec<U> derive(final Function<T[], U[]> mapper) {

            return new XVec<>(mapper.apply(this.data));
        }

        /**
         * 衍生化出一个 同构对象:元素级别变换
         * 
         * @param <U>    mapper的结果 元素类型
         * @param mapper 元素变换器 t->u
         * @return 以U为元素类型的 XVec
         */
        @SuppressWarnings("unchecked")
        public <U> XVec<U> derive2(final Function<T, U> mapper) {

            final var n = this.data.length;
            U[] aa = null;
            for (int i = 0; i < this.data.length; i++) {
                final var u = mapper.apply(this.data[i]);
                if (aa == null)
                    aa = (U[]) Array.newInstance(u.getClass(), n);
                aa[i] = u;
            } // for

            return new XVec<>(aa);
        }

        /**
         * 术语取自 haskell 的 functor <br>
         * 使用mapper转换集合data数据，生成u类型XVec
         * 
         * @param <U>    结果的元素类型
         * @param mapper 数据流映射函数,t->u
         * @return U类型的数据流
         */
        public <U> XVec<U> fmap(final Function<T, U> mapper) {

            final var dd = Arrays.stream(data).map(mapper).collect(Collectors.toList());

            return XVec.OF(dd);
        }

        /**
         * 术语取自 haskell 的 functor <br>
         * 使用mapper转换集合data数据，生成u类型XVec
         * 
         * @param <U>    结果的元素类型
         * @param mapper 数据流映射函数,(i:元素索引从0开始,t:元素值)->u
         * @return U类型的数据流
         */
        public <U> XVec<U> fmap(final BiFunction<Long, T, U> mapper) {

            final var al = new AtomicLong(0L);
            final var dd = Arrays.stream(data).map(e -> mapper.apply(al.getAndIncrement(), e))
                    .collect(Collectors.toList());

            return XVec.OF(dd);
        }

        /**
         * 二元变换:可以改变t值与类型的shuffle (i,t)->weightable <br>
         * 先为数据指定权重，而后给予重排顺序
         *
         * @param <U>    结果的元素类型
         * @param mapper 元素变换器,把T 变换成一个带有权重的 T值 : <br>
         *               (i:索引序号从0开始,t:元素值) -> weightable&lt;u&gt;
         * @return XVec &lt;U&gt;
         */
        public <U> XVec<U> shuffleX(final BiFunction<Integer, T, Weightable<U>> mapper) {
            
            return this.fmap((i, t) -> mapper.apply(i.intValue(), t)).sorted(Weightable::weight)
                    .fmap(Weightable::value);
        }
        
        /**
         * 后缀X 表示是 返回的结果是 XVec类型 <br>
         * 数据切片 ( slice XVec )
         * 
         * @param sizes 切片尺寸大小,切片尺寸会被循环使用
         * @return 切片集合
         */
        public XVec<XVec<T>> sliceX(final int... sizes) {
            
            return XVec.OF(this.slice(XVec::new, sizes));
        }
        
        /**
         * 后缀X 表示是 返回的结果是 XVec类型 <br>
         * 数据切片 ( slice XVec )
         * 
         * @param <U>    列表元素类型
         * @param mapper 结果映射函数 [tt]->U
         * @param sizes  切片尺寸大小,切片尺寸会被循环使用
         * @return 切片集合:XVec结构
         */
        public <U> XVec<U> sliceX(final Function<T[], U> mapper, final int... sizes) {
            
            return XVec.OF(this.slice(mapper, sizes));
        }
        
        /**
         * 数据扁平化
         * @param <U> 扁平化的元素类型
         * @param u 类型占位符，用于编译提示
         * @return 数据扁平化 向量
         */
        public <U> XVec<U> flatX(final U u){
            return this.flatX((Class<U>)null);
        }
        
        /**
         * 数据扁平化
         * @param <U> 扁平化的元素类型
         * @param uclazz 类型占位符，用于编译提示
         * @return 元为U类型的向量
         */
        public <U> XVec<U> flatX(final Class<U> uclazz){
            return XVec.flat(this,uclazz);
        }
        
        /**
         * 拉链成流
         * 
         * @param <V>   第二位置元素类型
         * @param <P>   结果元素类型
         * @param seq   第二位置元素序列
         * @param pctor 结果元组构造函数:(k,v)->p
         * @return P类型的二元元组流
         */
        public <V, P extends IVPair<T, V, ?>> XVec<P> zip(final Seq<V> seq, final BiFunction<T, V, P> pctor) {
            @SuppressWarnings("unchecked")
            final BiFunction<T, V, P> _pctor = pctor == null ? (k, v) -> (P) IVPair.OF(k, v) : pctor;
            final var xvec = this.zipS(seq, _pctor).collect(XVec.xveclc());
            return xvec;
        }
        
        /**
         * 拉链成流
         * 
         * @param <V>   第二位置元素类型
         * @param <P>   结果元素类型
         * @param cc    第二位置元素序列
         * @param pctor 结果元组构造函数:(k,v)->p
         * @return P类型的二元元组流
         */
        public <V, P extends IVPair<T, V, ?>> XVec<P> zip(final Collection<V> cc, final BiFunction<T, V, P> pctor) {
            return this.zip(XVec.OF(cc),pctor);
        }
        
        /**
         * 拉链成流
         * 
         * @param <V>   第二位置元素类型
         * @param <P>   结果元素类型
         * @param vv    第二位置元素序列
         * @param pctor 结果元组构造函数:(k,v)->p
         * @return P类型的二元元组流
         */
        public <V, P extends IVPair<T, V, ?>> XVec<P> zip(final V[] vv, final BiFunction<T, V, P> pctor) {
            return this.zip(XVec.OF(vv),pctor);
        }

        /**
         * 拉链成流
         * 
         * @param <V>   第二位置元素类型
         * @param seq   第二位置元素序列
         * @return IVP类型的二元元组流
         */
        public <V> XVec<IVPair<T, V, ?>> zip(final Seq<V> seq) {
            return zip(seq,null);
        }
        
        /**
         * 实例构造<br>
         * OF大写是为了避免与后续的继承类(子类)的of方法相冲突,即区别对待的突出,这是一个始祖级构造实例方法<br>
         *
         * 构造一个向量对象 <br>
         * 之所以不采用of是为了不予NVec的of发生冲突<br>
         *
         * @param <T> 向量元素类型
         * @param tt  向量元素数组
         * @return XVec 向量
         */
        @SafeVarargs
        public static <T> XVec<T> OF(final T... tt) {

            return new XVec<>(tt);
        }

        /**
         * 实例构造<br>
         *OF大写是为了避免与后续的继承类(子类)的of方法相冲突,即区别对待的突出,这是一个始祖级构造实例方法<br>
         *
         * 构造一个向量对象 <br>
         * 之所以不采用of是为了不予NVec的of发生冲突<br>
         *
         * @param <T>    向量元素类型
         * @param stream 向量元素的流(需要是有限流,否则会造成读取灾难)
         * @return XVec 向量
         */
        public static <T> XVec<T> OF(final Stream<T> stream) {

            return OF(stream.collect(Collectors.toList()));
        }

        /**
         * 实例构造<br>
         * OF大写是为了避免与后续的继承类(子类)的of方法相冲突,即区别对待的突出,这是一个始祖级构造实例方法<br>
         *
         * 构造一个向量对象 <br>
         * 之所以不采用of是为了不予NVec的of发生冲突<br>
         *
         * @param <T>  向量元素类型
         * @param coll 向量元素的集合
         * @return XVec
         */
        public static <T> XVec<T> OF(final Collection<T> coll) {

            return new XVec<>(coll.toArray(Seq.aagen(Seq.componentType(coll))));
        }
        
        /**
         * 实例构造<br>
         * OF大写是为了避免与后续的继承类(子类)的of方法相冲突,即区别对待的突出,这是一个始祖级构造实例方法<br>
         * <p>
         * 构造一个向量对象，带有索引序号生成器 <br>
         * 之所以不采用of是为了不予NVec的of发生冲突<br>
         *
         * @param <T>       向量元素类型
         * @param n         向量长度 大于等于1的正整数
         * @param generator 向量元素的生成器:int索引序号->T, 索引序号从0开始
         * @return XVec 向量
         */
        public static <T> XVec<T> OF(final int n, Function<Integer, T> generator) {

            return Range.of(n).stream(e -> generator.apply(e.intValue())).collect(Range.aaclc(XVec::OF));
        }

        /**
         * 把一个对象展开成单层元素
         * @param obj 被展开的数据对象
         * @return XVec的展开元素对象
         */
        public static XVec<Object> flat(final Object obj){
            
            return XVec.flat(obj,(i,e)->e);
        }
        
        /**
         * 把一个对象展开成单层元素
         * @param <T> 结果向量的元素类型
         * @param obj 被展开的数据对象
         * @param tclazz 类型标记,用于向编译器提供T的类型。使用强制转换的方式给予进行obj->T类型的变换
         * @return XVec的展开元素对象
         */
        @SuppressWarnings("unchecked")
        public static <T> XVec<T> flat(final Object obj, final Class<T>tclazz){
            
            return flat(obj,(idx,e)->(T)e);
        }
        
        /**
         * 把一个对象展开成单层元素
         * @param <T> 结果向量的元素类型
         * @param obj 被展开的数据对象
         * @param mapper 结果类型的变换器 (index, Object)->T
         * @return XVec的展开元素对象
         */
        public static <T> XVec<T> flat(final Object obj, final BiFunction<List<Integer>,Object,T> mapper){
            
            final var path = new LinkedList<Integer>();// 路径索引
            
            return flat(obj,mapper,path);
        }

        /**
         * 把一个对象展开成单层元素 <br>
         * 展开类型包括:Object[],Seq
         * @param <T> 结果向量的元素类型
         * @param obj 被展开的数据对象
         * @param mapper 结果类型的变换器:索引路径键值对 (path, Object)->T
         * @param path 路径索引
         * @return XVec的展开元素对象
         */
        @SuppressWarnings("unchecked")
        public static <T> XVec<T> flat(final Object obj, final BiFunction<List<Integer>,Object,T> mapper,
            final LinkedList<Integer> path){
            
            final var ll = new LinkedList<T>();// 结果列表
            final BiFunction<List<Integer>, Object, T> accessor = mapper == null ? (p, o) -> (T) o : mapper; // 数据访问器
            
            final Consumer<Object[]> dfs = oo -> { // deep first search
                for (int i = 0; i < oo.length; i++) {
                    path.add(i); // 在路径种加入第i项的元素索引
                    ll.addAll(XVec.flat(oo[i], accessor,path).list());
                    path.removeLast(); // 遍历完第i项之后,给予移除
                } //for
            };
            
            if (obj instanceof Object[]) {// 对数组类型的数据进行深度遍历
                dfs.accept((Object[]) obj);
            } else if (obj instanceof Seq) {// 对Seq类型的数据进行深度遍历
                dfs.accept(((Seq<Object>) obj).toArray());
            } else {// 非数组元素保持输出到结果列表之中
                ll.add(accessor.apply(path, obj));
            } // if
            
            return new XVec<>(ll.toArray(n->(T[])Array.newInstance(Seq.componentType(ll), n)));
        }

        /**
         * 扁平化一个对象使之成为一个IVP列表
         * @param obj 待扁平化的数据，一般为一个多维数组。
         * @return IndexValuePair 扁平化的数据
         */
        public static List<DataPoint<Object>> flatten(final Object obj){
            
            return flatten(obj,e->e);
        }
        
        /**
         * 扁平化一个对象使之成为一个IVP列表
         * @param <T> IndexValuePair 的元素类型
         * @param obj 待扁平化的数据，一般为一个多维数组。
         * @param tclazz 类型标记,用于向编译器提供T的类型。使用强制转换的方式给予进行obj->T类型的变换
         * @return IndexValuePair 扁平化的数据
         */
        @SuppressWarnings("unchecked")
        public static <T> List<DataPoint<T>> flatten(final Object obj, final Class<T> tclazz){
            
            return flatten(obj,o->(T)o);
        }
        
        /**
         * 扁平化一个对象使之成为一个IVP列表
         * @param <T> IndexValuePair 的元素类型
         * @param obj 待扁平化的数据，一般为一个多维数组。
         * @return IndexValuePair 扁平化的数据
         */
        public static <T> List<DataPoint<T>> flatten(final Object obj, final Function<Object,T> mapper){
            
            final List<DataPoint<T>> ivps = new LinkedList<>(); // 返回结果
            
            XVec.flat(obj,(path,o) -> {// 路径缩影
                final var ivp = new DataPoint<>(path.stream()
                    .mapToInt(e->e).toArray(),mapper.apply(o));
                ivps.add(ivp);
                return ivp;
            });
            
            return ivps; // 返回结果
        }
        
        /**
         * 扁平化一个对象使之成为一个IVP列表
         * @param obj 待扁平化的数据，一般为一个多维数组。
         * @return IndexValuePair 扁平化的数据
         */
        public static Stream<DataPoint<Object>> flattenS(final Object obj){
            
            return flattenS(obj,o->o);
        }

        /**
         * 扁平化一个对象使之成为一个IVP列表
         * @param <T> IndexValuePair 的元素类型
         * @param obj 待扁平化的数据，一般为一个多维数组。
         * @param tclazz 类型标记,用于向编译器提供T的类型。使用强制转换的方式给予进行obj->T类型的变换
         * @return IndexValuePair 扁平化的数据
         */
        @SuppressWarnings("unchecked")
        public static <T> Stream<DataPoint<T>> flattenS(final Object obj, final Class<T> tclazz){
            
            return flattenS(obj,o->(T)o);
        }

        /**
         * 扁平化一个对象使之成为一个IVP列表
         * 
         * @param <T> IndexValuePair 的元素类型
         * @param obj 待扁平化的数据，一般为一个多维数组。
         * @return IndexValuePair 扁平化的数据
         */
        public static <T> Stream<DataPoint<T>> flattenS(final Object obj, final Function<Object, T> mapper) {

            return flatten(obj, mapper).stream();
        }

        /**
         * xvec归集器
         *
         * @param mapper 类型变换器 t->u
         * @param <T>    源数据类型
         * @param <U>    目标数据类型
         * @return 把T类型的流归结成XVec&lt;U&gt; 类型的归集器
         */
        public static <T, U> Collector<T, List<U>, XVec<U>> xveclc(final Function<T, U> mapper) {
            return Collector.of(ArrayList::new, (List<U> aa, T t) -> aa.add(mapper.apply(t)), (aa, bb) -> {
                aa.addAll(bb);
                return aa;
            }, XVec::OF);
        }

        /**
         * xvec归集器
         *
         * @param <T> 源数据类型
         * @return 把T类型的流归结成XVec&lt;T&gt; 类型的归集器
         */
        public static <T> Collector<T, List<T>, XVec<T>> xveclc() {
            return xveclc(e -> e);
        }

    }// XVec

    /**
     * 数值向量(Number Vector) 即 长度为n的数字元组<br>
     * <br>
     * 一个数值向量用于表示一个 点概念:小则无内的意思，<br>
     * 即它的主要作用就是 通过累加(结构化)的方式 组合形成 其他的 更富有实际意义  的 实在 概念。<br>
     * 所以向量 是一个 (原材料概念), 素材概念, 是用于 构成更高级的概念的 概念 即 单元概念 或是 原子概念  <br>
     * 
     * @author gbench
     */
    public static class NVec extends XVec<Double> {
        
        /**
         * 数值类型的向量
         * @param vv 向量的数据元素序列
         */
        public NVec(final int[] vv){
            
            super(Arrays.stream(vv==null?new int[] {}:vv).mapToObj(Double::valueOf).toArray(Double[]::new));
        }
        
        /**
         * 数值类型的向量
         * @param vv 向量的数据元素序列
         */
        public NVec(final double[] vv){
            
            super(Arrays.stream(vv==null?new double[] {}:vv).boxed().toArray(Double[]::new));
        }
        
        /**
         * 数值类型的向量
         * @param vv 向量的数据元素序列,vv 数据 直接引用。
         */
        public NVec(final Double[] vv){
            
            super(vv);
        }
        
        /**
         * 数值类型的向量
         * @param vv 向量的数据元素序列,vv 数据 拷贝引用
         */
        public NVec(final Number[] vv){
            
            super(Arrays.stream(vv==null?new Number[] {}:vv).map(e->e==null?null:e.doubleValue()).toArray(Double[]::new));
        }
        
        /**
         * 数值类型的向量
         * @param rng 区间范围对象
         */
        public NVec(final Range rng){
            
            this(rng.dblA());
        }
        
        /**
         * 数值类型的向量
         * @param vec 通用向量对象,当vec创建一个data为[]的对象。
         */
        public NVec(final XVec<? extends Number> vec){
          
           this(Seq.unboxed(vec));
        }
        
        /**
         * 构造一个克隆体
         */
        public NVec duplicate() {

            return NVec.of(this);
        }

        /**
         * 构造一组复制品
         *
         * @param <X> 结果类型
         * @param n 衍生（复制）的规模次数
         * @param derivate 衍生器
         * @return T 的数据流
         */
        public <X> Stream<X> duplicateNS(final int n, final BiFunction<Integer, NVec, X> derivate) {

            return super.duplicateS2(n, (i,data)->derivate.apply(i,new NVec(data)));
        }

        /**
         * 构造一组复制品(复制n次)
         *
         * @param n 衍生（复制）的规模次数
         * @return NVec 的数据流 长度为n
         */
        public <X> Stream<NVec> replicateNS(final int n) {

            return this.duplicateNS(n,(i,x)->x);
        }
        
        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值<br>
         * vec.evaluate((i,v)->vec.set(i,v),1,23);<br>
         * @param callback 回调函数
         * @param oo (索引,值) 的 序列 :索引1,值1,索引2,值2,...<br>
         * 注意 索引是为Integer类型,Value 是T类型。oo 需要在传入的时候 保证各自类型的正确性
         * @return NVec 自身以便实现链式编程
         */
        public NVec evaluate(final BiConsumer<Integer,Double> callback,
            final Object ... oo) {
            
           return (NVec)super.evaluate(callback, oo);
        }
        
        /**
         * 保持结构不变的内容拷贝/修改，与update的区别就是copy不是修改原数据自身值，只是先生成一个拷贝对象然后修改
         * @param copyer 元素拷贝算法 : double->double
         * @return 新的NVec对象
         */
        public NVec copy(final Function<Double,Double> copyer) {
            
            return NVec.of(super.copy(copyer).data);
        }
        
        /**
         * 保持结构不变的内容拷贝/修改，与update的区别就是copy不是修改原数据自身值，只是先生成一个拷贝对象然后修改
         * @param copyer 元素拷贝算法 : (integer,double)->double
         * @return 新的NVec对象
         */
        public NVec copy(final BiFunction<Integer,Double,Double> copyer) {
            
            return NVec.of(super.copy(copyer).data);
        }
        
        /**
         * 生成以元素顺序与当前元素属性相反的 向量。
         * 如 [1,2,3] -> [3,2,1]
         * @return 元素顺序与当前元素属性相反的 向量
         */
        public NVec reverse() {
            return NVec.of(super.reverse().data);
        }

        /**
         * reverse 别名<br>
         * 生成以元素顺序与当前元素属性相反的 向量。
         * 如 [1,2,3] -> [3,2,1]
         * @return 元素顺序与当前元素属性相反的 向量
         */
        public NVec rev() {
            return this.reverse();
        }

        /**
         * reverse 别名<br>
         * 生成以元素顺序与当前元素属性相反的 向量。
         * 如 [1,2,3] -> [3,2,1]
         * @return 元素顺序与当前元素属性相反的 向量
         */
        public NVec R() {
            return this.reverse();
        }
        
        /**
         * 设置第i个元素的值
         * 
         * @param i 设置的位置，从0开始
         * @param value 设置的值
         * @return 对象本身以实现链式编程
         */
        public NVec set(final int i,Double value) {
            
            super.set(i, e->value);
            return this;
        }
        
        /**
         * 设置第i个元素的值
         * 
         * @param i 设置的位置，从0开始
         * @param valueer 设置的值的计算函数:dbl->dbl
         * @return 对象本身以实现链式编程
         */
        public NVec set(final int i,Function<Double,Double> valueer) {
            
            super.set(i, valueer);
            return this;
        }
        
        /**
         * 调换 i,j 两个位置的元素
         * @param i 大于等于0的整数,位置索引从0开始
         * @param j 大于等于0的整数,位置索引从0开始
         * @return NVec自身便于实现链式编程
         */
        public NVec swap(final int i,final int j) {
            
            super.swap(i, j);
            
            return this;
        }

        /**
         * 先做duplicate然后做idval_set <br>
         * 根据指定的索引位置，修改向量中对象位置的成分值
         * @param idx2values (索引,值) 的 序列 :索引1,值1,索引2,值2,...
         * @return 新生成的NVec
         */
        public NVec duplicateIVS(final Number ... idx2values) {

            return this.duplicate().idval_set(idx2values);
        }
        
        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值
         * @param idx2values (索引,值) 的 序列 :索引1,值1,索引2,值2,...
         * @return NVec 自身以便实现链式编程
         */
        public NVec idval_set(final Number ... idx2values) {
            
            final var size = idx2values.length;
            for(var i=0;i<size-1;i+=2) data[idx2values[i].intValue()]=idx2values[i+1].doubleValue();
            
            return this;
        }
        
        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值
         * @param idx2values (索引,值) 的 序列 :索引1,值1,索引2,值2,...
         * @return NVec 自身以便实现链式编程
         */
        public NVec idval_add(final Number ... idx2values) {
            
            final var size = idx2values.length;
            for(var i=0;i<size-1;i+=2) data[idx2values[i].intValue()] += idx2values[i+1].doubleValue();
            
            return this;
        }
        
        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值
         * @param idx2values (索引,值) 的 序列 :索引1,值1,索引2,值2,...
         * @return NVec 自身以便实现链式编程
         */
        public NVec idval_sub(final Number ... idx2values) {
            
            final var size = idx2values.length;
            for(var i=0;i<size-1;i+=2) data[idx2values[i].intValue()] -= idx2values[i+1].doubleValue();
            
            return this;
        }
        
        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值(被减去)
         * @param idx2values (索引,值) 的 序列 :索引1,值1,索引2,值2,...
         * @return NVec 自身以便实现链式编程
         */
        public NVec idval_sub2(final Number ... idx2values) {
            
            final var size = idx2values.length;
            for(var i=0;i<size-1;i+=2) 
                data[idx2values[i].intValue()] = idx2values[i+1].doubleValue()-data[idx2values[i].intValue()];
            
            return this;
        }
        
        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值
         * @param idx2values (索引,值) 的 序列 :索引1,值1,索引2,值2,...
         * @return NVec 自身以便实现链式编程
         */
        public NVec idval_mul(final Number ... idx2values) {
            
            final var size = idx2values.length;
            for(var i=0;i<size-1;i+=2) data[idx2values[i].intValue()] *= idx2values[i+1].doubleValue();
            
            return this;
        }
        
        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值
         * @param idx2values (索引,值) 的 序列 :索引1,值1,索引2,值2,...
         * @return NVec 自身以便实现链式编程
         */
        public NVec idval_div(final Number ... idx2values) {
            
            final var size = idx2values.length;
            for(var i=0;i<size-1;i+=2) data[idx2values[i].intValue()] /= idx2values[i+1].doubleValue();
            
            return this;
        }
        
        /**
         * 根据指定的索引位置，修改向量中对象位置的成分值(被出除去)
         * @param idx2values (索引,值) 的 序列 :索引1,值1,索引2,值2,...
         * @return NVec 自身以便实现链式编程
         */
        public NVec idval_div2(final Number ... idx2values) {
            
            final var size = idx2values.length;
            for(var i=0;i<size-1;i+=2) data[idx2values[i].intValue()] = 
                idx2values[i+1].doubleValue()/data[idx2values[i].intValue()];
            
            return this;
        }
        
        /**
         * 计算当前点与目标点nvec之间的距离
         * 
         * @param nvec 目标点,null 默认为原点
         * @return 计算当前点与目标点nvec之间的距离
         */
        public Double distance(final NVec nvec) {
            return this.sub(nvec == null ? NVec.of(0) : nvec).mutateT((NVec e) -> Math.sqrt(e.dot(e)));
        }

        /**
         * 计算当前点与原点之间的距离
         * 
         * @return 计算当前点与原点之间的距离
         */
        public Double distance() {
            return this.distance(null);
        }
        
        /**
         * 点积 运算 <br> 
         * 
         * 采用 循环 补位的方法,按照(this,nvec)的最大长度, 计算两个向量的 点积
         * @param nvec 另一个Nvec向量
         * @return 点集合运算的结果。
         */
        public Double dot(NVec nvec) {
            
            if(nvec.size()<1||this.size()<1)return null;
            
            return Stream.iterate(0d, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .reduce(0d,(a,i)->a+this.get(i.intValue()%this.size())*nvec.get(i.intValue()%nvec.size()));
        }
        
        /**
         * 向量间加法<br>
         * <br>
         * 把两个向量的同位置元素进行相加,并把和的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param nvec 另一个向量
         * @return NVec 和结果NVec
         */
        public NVec add(NVec nvec) {
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->this.dbl(i%this.size())+nvec.dbl(i%nvec.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量间减法<br>
         * <br>
         * this-nvec <br>
         * 把两个向量的同位置元素进行减法,并把差的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param nvec 另一个向量
         * @return NVec 差结果NVec
         */
        public NVec sub(NVec nvec) {
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->this.dbl(i%this.size())-nvec.dbl(i%nvec.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量间减法<br>
         * <br>
         * nvec-this <br>
         * 把两个向量的同位置元素进行减法,并把差的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param nvec 另一个向量
         * @return NVec 差结果NVec
         */
        public NVec sub2(NVec nvec) {
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->nvec.dbl(i%nvec.size())-this.dbl(i%this.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量间乘法<br>
         * <br>
         * 把两个向量的同位置元素进行相乘,并把积的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param nvec 另一个向量
         * @return NVec 积结果NVec
         */
        public NVec mul(NVec nvec) {
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->this.dbl(i%this.size())*nvec.dbl(i%nvec.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量间除法<br>
         * <br>
         * this/nvec <br>
         * 把两个向量的同位置元素进行除法,并把商的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param nvec 另一个向量
         * @return NVec 商结果NVec
         */
        public NVec div(NVec nvec) {
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->this.dbl(i%this.size())/nvec.dbl(i%nvec.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量间除法<br>
         * <br>
         * nvec/this <br>
         * 把两个向量的同位置元素进行减法,并把差的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param nvec 另一个向量
         * @return NVec 商结果NVec
         */
        public NVec div2(NVec nvec) {
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->nvec.dbl(i%nvec.size())/this.dbl(i%this.size())).toArray(Double[]::new));
        }
        
        
        /**
         * 向量常数间减法<br>
         * <br>
         * 把一个常数a 转换成 一个 长度为1的向量,即 NVec.of(a) ,然后 开展向量运算 <br> 
         * 
         * 把两个向量的同位置元素进行相加,并把和的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param a 常数
         * @return NVec 和结果NVec
         */
        public NVec add(final Number a) {
            
            final var nvec = NVec.of(a);
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->this.dbl(i%this.size())+nvec.dbl(i%nvec.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量常数间减法<br>
         * <br>
         * 把一个常数a 转换成 一个 长度为1的向量,即 NVec.of(a) ,然后 开展向量运算 <br> 
         * 
         * this-nvec <br>
         * 把两个向量的同位置元素进行减法,并把差的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param a 常数
         * @return NVec 差结果NVec
         */
        public NVec sub(final Number a) {
            
            final var nvec = NVec.of(a);
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->this.dbl(i%this.size())-nvec.dbl(i%nvec.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量常数间减法<br>
         * <br>
         * 把一个常数a 转换成 一个 长度为1的向量,即 NVec.of(a) ,然后 开展向量运算 <br> 
         * 
         * nvec-this <br>
         * 把两个向量的同位置元素进行减法,并把差的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param a 常数
         * @return NVec 差结果NVec
         */
        public NVec sub2(final Number a) {
            
            final var nvec = NVec.of(a);
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->nvec.dbl(i%nvec.size())-this.dbl(i%this.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量常数间乘法<br>
         * <br>
         * 把一个常数a 转换成 一个 长度为1的向量,即 NVec.of(a) ,然后 开展向量运算 <br> 
         * 
         * 把两个向量的同位置元素进行相乘,并把积的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param a 常数
         * @return NVec 积结果NVec
         */
        public NVec mul(final Number a) {
            
            final var nvec = NVec.of(a);
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
            .map(i->this.dbl(i%this.size())*nvec.dbl(i%nvec.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量常数间除法<br>
         * <br>
         * 把一个常数a 转换成 一个 长度为1的向量,即 NVec.of(a) ,然后 开展向量运算 <br> 
         * 
         * this/nvec <br>
         * 把两个向量的同位置元素进行除法,并把商的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param a 常数
         * @return NVec 商结果NVec
         */
        public NVec div(final Number a) {
            
            final var nvec = NVec.of(a);
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
            .map(i->this.dbl(i%this.size())/nvec.dbl(i%nvec.size())).toArray(Double[]::new));
        }
        
        /**
         * 向量常数间除法<br>
         * <br>
         * 把一个常数a 转换成 一个 长度为1的向量,即 NVec.of(a) ,然后 开展向量运算 <br> 
         * 
         * nvec/this <br>
         * 把两个向量的同位置元素进行减法,并把差的结果序列组合成向量NVec <br>
         * 计算过程采用 循环补位的方式 ,按照 this 和  nvec 的最大长度进行计算。 <br>
         * @param a 常数
         * @return NVec 商结果NVec
         */
        public NVec div2(final Number a) {
            
            final var nvec = NVec.of(a);
            
            return NVec.of(Stream.iterate(0, i->i+1).limit(Math.max(this.size(),nvec.size()))
                .map(i->nvec.dbl(i%nvec.size())/this.dbl(i%this.size())).toArray(Double[]::new));
        }
        
        /**
         * 连乘
         * @return 连乘 结果
         */
        public Double product() {
            
            return Arrays.stream(this.data()).reduce(1d, (aa,a)->aa*a);
        }
        
        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * 连乘
         * @return 连乘 结果
         */
        public NVec productN() {
            
            return NVec.of(this.product());
        }
        
        /**
         * 连加
         * @return 连加结果
         */
        public Double sum() {
            
            return Arrays.stream(this.data()).reduce(0d, Double::sum);
        }
        
        /**
         * 连加
         * @return 连加结果
         */
        public NVec sumN() {
            
            return NVec.of(this.sum());
        }
        
        /**
         * 统计信息(Double 类型)
         * @return 统计信息
         */
        public DoubleSummaryStatistics stats() {
            
            return Arrays.stream(this.data()).collect(Collectors.summarizingDouble(e->e));
        }
        
        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * 平均数
         * @return 平均数
         */
        public Double mean() {
            
            return this.stats().getAverage();
        }
        
        /**
         * 平均数
         * @return 平均数
         */
        public NVec meanN() {
            
            return NVec.of(this.mean());
        }
        
        /**
         * 最大值
         * @return 最大值
         */
        public Double max() {
            
            return this.stats().getMax();
        }
        
        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * 最大值
         * @return 最大值
         */
        public NVec maxN() {
            
            return NVec.of(this.max());
        }
        
        /**
         * 最小值
         * @return 最小值
         */
        public Double min() {
            
            return this.stats().getMin();
        }
        
        /**
         * 最小值
         * @return 最小值
         */
        public NVec minN() {
            
            return NVec.of(this.min());
        }

        /**
         * 返回 [min,max]的range 对象，步长默认为1
         * @return 返回 [min,max]的range 对象
         */
        public Range range(){

            final var stats = this.stats();
            return Range.of(stats.getMin(),stats.getMax());
        }

        /**
         * 返回 [min,max的二元组]
         * @return [min,max的二元组]
         */
        public NVec rangeN(){

            final var stats = this.stats();
            return NVec.of(stats.getMin(),stats.getMax());
        }

        /**
         * 返回 [min,max的列表]
         * @return [min,max的列表]
         */
        public List<Double> rangeL(){

            return this.rangeN().dblL();
        }

        /**
         * 返回 [min,max的数组]
         * @return [min,max的数组]
         */
        public Double[] rangeA(){

            return this.rangeN().data;
        }
        
        /**
         * variance population <br>
         * 总体方差:<br>
         * 方差: 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @return 方差
         */
        public Double varp() {
            
            return this.varp(this);
        }
        
        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * variance population <br>
         * 总体方差:<br>
         * 方差: 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @return 方差
         */
        public NVec varpN() {
            
            return NVec.of(this.var());
        }
        
        /**
         * variance population <br>
         * 总体方差:<br>
         * 方差: 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param vec 另一个向量
         * @return 方差
         */
        public Double varp(final NVec vec) {
            
            final var exy = this.dot(vec)/(this.size());
            final var exey = this.mean()*vec.mean();
            
            return exy-exey;
        }
        
        /**
         * variance sample <br>
         * 样本方差:<br>
         * 方差: 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @return 方差
         */
        public Double var() {
            
            return this.var(this);
        }
        
        /**
         * variance sample <br>
         * 样本方差:<br>
         * 方差: 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param vec 另一个向量
         * @return 方差
         */
        public Double var(final NVec vec) {
            
            return this.varN(vec).get(0);
        }
        
        /**
         * variance sample <br>
         * 样本方差<br>
         * 方差: 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param vec 另一个向量
         * @return 方差
         */
        public NVec varN(final NVec vec) {
            
            final var xc = this.meanN().sub2(this);
            final var yc = vec.meanN().sub2(vec);
            final var n = vec.size()-1;
            return xc.mul(yc).sumN().div(n);
        }
        
        /**
         * standard deviation population <br>
         * 总体标准差:<br>
         * 标准差:  注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @return 标准差
         */
        public Double sdp() {
            
            return this.sd(this);
        }
        
        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * standard deviation population <br>
         * 总体标准差:<br>
         * 标准差:  注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @return 标准差
         */
        public NVec sdpN() {
            
            return NVec.of(sdp());
        }
        
        /**
         * standard deviation population <br>
         * 总体标准差:<br>
         * 协方差的标准差 : 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param nvec 另一个向量
         * @return 标准差
         */
        public Double sdp(final NVec nvec) {
            
            return Math.sqrt(this.varp(nvec));
        }
        
        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * standard deviation population <br>
         * 总体标准差:<br>
         * 协方差的标准差 : 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param nvec 另一个向量
         * @return 标准差
         */
        public NVec sdpN(final NVec nvec) {
            
            return NVec.of(sdp(nvec));
        }
        
        /**
         * standard deviation sample <br>
         * 样本标准差:<br>
         * 标准差:  注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @return 标准差
         */
        public Double sd() {
            
            return this.sd(this);
        }

        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * standard deviation sample <br>
         * 样本标准差:<br>
         * 标准差:  注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @return 标准差
         */
        public NVec sdN() {
            
            return NVec.of(sd());
        }

        /**
         * standard deviation sample <br>
         * 样本标准差:<br>
         * 协方差的标准差 : 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param nvec 另一个向量
         * @return 标准差
         */
        public Double sd(final NVec nvec) {
            
            return Math.sqrt(this.var(nvec));
        }

        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * standard deviation sample <br>
         * 样本标准差:<br>
         * 协方差的标准差 : 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param nvec 另一个向量
         * @return 标准差
         */
        public NVec sdN(final NVec nvec) {
            
            return NVec.of(this.sd(nvec));
        }

        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * correlation popuplation <br>
         * 总体相关系数:<br>
         * 协方差的标准差 : 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param nvec 另一个向量
         * @return 相关系数
         */
        public Double corp(final NVec nvec) {
            
            return this.varp(nvec)/(this.sdp()*nvec.sdp());
        }
        
        /**
         * correlation popuplation <br>
         * 总体相关系数:<br>
         * 协方差的标准差 : 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param nvec 另一个向量
         * @return 相关系数
         */
        public NVec corpN(final NVec nvec) {
            
            return NVec.of(this.corp(nvec));
        }
        
        /**
         * correlation sample <br>
         * 总体相关系数:<br>
         * 协方差的标准差 : 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param nvec 另一个向量
         * @return 相关系数
         */
        public Double cor(final NVec nvec) {
            
            return this.var(nvec)/(this.sdp()*nvec.sd());
        }
        
        /**
         * 后缀N 表示是  返回的结果是 NVec类型 <br>
         * correlation sample <br>
         * 总体相关系数:<br>
         * 协方差的标准差 : 注意 总体方差 是[除以n],不是样本方差[除以(n-1)]
         * @param nvec 另一个向量
         * @return 相关系数
         */
        public NVec corN(final NVec nvec) {
            
            return NVec.of(this.cor(nvec));
        }
        
        /**
         * 数据中心化 [均值中心化]
         * @return 以mean均值为中心的数据NVec
         */
        public NVec centering() {
            
            return this.centering(null);
        }
        
        /**
         * 数据中心化 使用center作为中心点<br>
         * center 作为中心点 <br> 
         * @param center 中心点位置 ,null 默认为 mean 均值
         * @return 以center为中心的数据NVec
         */
        public NVec centering(final Number center) {
            
            return NVec.of(this.sub(center==null?this.mean():center.doubleValue()));
        }
        
        /**
         * 仿射变换<br>
         * 平移
         * @param offset 偏移大小
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_offset(final Number offset) {
            
            return this.idval_add(0,offset,1,offset);
        }

        /**
         * 仿射变换<br>
         * 平移
         * @param offsetx x方向偏移大小
         * @param offsety x方向偏移大小
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_offset(final Number offsetx, final Number offsety) {
            
            return this.idval_add(0,offsetx,1,offsety);
        }
        
        /**
         * 仿射变换<br>
         * 平移
         * @param nvec [offsetx x方向偏移大小,offsety x方向偏移大小]
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_offset(final NVec nvec) {
            
            return this.idval_add(0,nvec.get(0),1,nvec.get(1));
        }
        
        /**
         * 仿射变换<br>
         * 缩放
         * @param nvec [scalex 第一维度 缩放大小,scaley y 第二维度 缩放大小]
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_scale(final NVec nvec) {
            
            return this.idval_mul(0,nvec.get(0),1,nvec.get(1));
        }
        
        /**
         * 仿射变换<br>
         * 缩放一下
         * @param scale 维度 缩放大小
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_scale(final Number scale) {
            
            return this.idval_mul(0,scale,1,scale);
        }
        
        /**
         * 仿射变换<br>
         * 缩放一下
         * @param scalex x 第一维度 缩放大小
         * @param scaley y 第二维度 缩放大小
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_scale(final Number scalex, final Number scaley) {
            
            return this.idval_mul(0,scalex,1,scaley.doubleValue());
        }
        
        /**
         * 仿射变换<br>
         * 先缩放然后平移:affine_scale_offset 的别名
         * @param scale 缩放比例
         * @param offset x,y 方向平移量
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_scale_offset(final Number scale, final Number offset) {
            
            return this.affine_scale(scale).affine_offset(offset);
        }
        
        /**
         * 仿射变换<br>
         * 先缩放然后平移:affine_scale_offset 的别名
         * @param scale 缩放比例
         * @param offsetx x方向平移量
         * @param offsety y方向平移量
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_scale_offset(final Number scale, final Number offsetx, final Number offsety) {
            
            return this.affine_scale(scale).affine_offset(offsetx,offsety);
        }
        
        /**
         * 仿射变换<br>
         * 先缩放然后平移
         * @param scalex x方向缩放比例
         * @param scaley y方向缩放比例
         * @param offsetx x方向平移量
         * @param offsety y方向平移量
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine_scale_offset(final Number scalex, final Number scaley, 
            final Number offsetx, final Number offsety) {
            
            return this.affine_scale(scalex,scaley).affine_offset(offsetx,offsety);
        }
        
        /**
         * 仿射变换<br>
         * 先缩放然后平移
         * @param scale x,y 方向的 缩放比例
         * @param offset x,y 方向平移量
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine(final Number scale, final Number offset) {
            
            return this.affine_scale_offset(scale, offset);
        }
        
        /**
         * 仿射变换<br>
         * 先缩放然后平移
         * @param scale x,y 方向的 缩放比例
         * @param offsetx x方向平移量
         * @param offsety y方向平移量
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine1(final Number scale, final Number offsetx, final Number offsety) {
            
            return this.affine_scale_offset(scale,scale, offsetx, offsety);
        }
        
        /**
         * 仿射变换<br>
         * 先缩放然后平移
         * @param scalex x方向缩放比例
         * @param scaley y方向缩放比例
         * @param offset x与y 方向上的 平移量
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine2(final Number scalex, final Number scaley, final Number offset) {
            
            return this.affine_scale_offset(scalex, scaley, offset, offset);
        }
        
        /**
         * 仿射变换<br>
         * 先缩放然后平移 : affine_scale_offset 的别名
         * @param scalex x方向缩放比例
         * @param scaley y方向缩放比例
         * @param offsetx x方向平移量
         * @param offsety y方向平移量
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine(final Number scalex, final Number scaley,
            final Number offsetx, final Number offsety) {
            
            return this.affine_scale_offset(scalex, scaley, offsetx, offsety);
        }

        /**
         * 仿射变换<br>
         * 先缩放然后平移 : affine_scale_offset 的别名
         * @param nvec 反射变化的系数 [scalex:x方向缩放比例, scaley:y方向缩放比例, offsetx:x方偏移量, offsety:y方偏移量]
         * @return NVec 自身以便实现链式编程
         */
        public NVec affine(final NVec nvec ) {

            return this.affine_scale_offset(nvec.get(0),nvec.get(1),nvec.get(2),nvec.get(3));
        }

        /**
         * 提取 第 i 个索引位置 的整型值
         * @param i 元素索引号,从0开始 不成超多或等于 size
         * @return 第 i 个索引位置 的整型值
         */
        public Integer i4(final int i) {
            
            final var d = this.get(i);
            if(d==null)return null;
            
            return d.intValue();
        }
        
        /**
         * 提取 第 i 个索引位置 的 双精度值
         * @param i 元素索引号,从0开始 不成超多或等于 size
         * @return  第 i 个索引位置 的 双精度值
         */
        public Double dbl(final int i) {
            
            final var d = this.get(i);

            return d;
        }
        
        /**
         * 提取 第 i 个索引位置 的  长整型数值
         * @param i 元素索引号,从0开始, 不成超多或等于 size
         * @return  第 i 个索引位置 的 长整型数值
         */
        public Long lng(final int i) {
            
            final var d = this.get(i);
            if(d==null)return null;
            
            return d.longValue();
        }

        /**
         * 整型数组
         * 
         * @return int[] 整型数组
         */
        public int[] ints() { // 使用for 循环单独提高效率

            final var len = this.data.length;
            final var aa = new int[len];
            for (int i = 0; i < len; i++)
                aa[i] = data[i].intValue();
            
            return aa;
        }
        
        /**
         * 整数列表
         * 
         * @return 整数列表
         */
        public List<Integer> intL() { // 使用for 循环单独提高效率

            return this.list(Double::intValue);
        }
        
        /**
         * 整数列表
         * 
         * @return 整数列表
         */
        public Integer[] integers() { // 使用for 循环单独提高效率

            return this.list(Double::intValue).toArray(Integer[]::new);
        }

        /**
         * 整数列表 integers 别名函数
         *
         * @return 整数列表
         */
        public Integer[] intA() { // 使用for 循环单独提高效率

            return integers();
        }
        
        /**
         * 双精度数组
         * 
         * @return 双精度数组
         */
        public double[] dbls() {
            
            final var len = this.data.length;
            final var aa = new double[len];
            for (int i = 0; i < len; i++)
                aa[i] = data[i].intValue();
            
            return aa;
        }
        
        /**
         * 双精度列表
         * 
         * @return Double 双精度列表
         */
        public List<Double> dblL() { // 使用for 循环单独提高效率

            return this.list(e->e);
        }
        
        /**
         * 双精度数组
         * 
         * @return 双精度数组
         */
        public Double[] doubles() { // 使用for 循环单独提高效率

            return this.list(e->e).toArray(Double[]::new);
        }

        /**
         * 双精度数组 doubles 别名函数
         *
         * @return 双精度数组
         */
        public Double[] dblA() { // 使用for 循环单独提高效率

            return this.doubles();
        }
        
        /**
         * 长整型数组
         * 
         * @return 长整型数组
         */
        public long[] lngs() {
            
            return Stream.of(data).mapToLong(Double::longValue).toArray();
        }
        
        /**
         * 长整型列表
         * 
         * @return 长整型列表
         */
        public List<Long> lngL() { // 使用for 循环单独提高效率

            return this.list(Double::longValue);
        }
        
        /**
         * 长整型数组
         * 
         * @return 整数列表
         */
        public Long[] longs() { // 使用for 循环单独提高效率

            return this.list(Double::longValue).toArray(Long[]::new);
        }

        /**
         * 长整型数组 longs 别名函数
         *
         * @return 整数列表
         */
        public Long[] lngA() { // 使用for 循环单独提高效率

            return longs();
        }
        
        /**
         * 提取大尾巴向量(除了1个小脑袋,其余全都是尾巴)
         * 
         * @return 除掉第一个元素的其他元素
         */
        public NVec bigtail() {
            
            return this.tail(this.size()-1);
        }

        /**
         * 提取尾部向量
         * 
         * @param num 尾部元素的数量,大于等于0的整数,当 num 大于数组长度时,返回全体元素
         * @return 提取尾部的长度为 num 的数据向量
         */
        public NVec tail(Number num) {

            return new NVec(super.tail(num).data);
        }

        /**
         * 提取大脑袋向量提取大尾巴向量(除了1个小尾巴,其余全都是大脑袋)
         * 
         * @return 除掉最后一个元素的其他元素
         */
        public NVec bighead() {
            
            return this.head(this.size()-1);
        }

        /**
         * 提取首部向量
         * 
         * @param num 头前的元素数量,大于等于0的整数,当 num 大于数组长度时,返回全体元素
         * @return 提取首部的长度为 num 的数据向量
         */
        public NVec head(final Number num) {

            return new NVec(super.head(num).data);
        }

        /**
         * 求出两个集合的交集
         * @param other 另一个 NVec 对象
         * @return 集合差对象
         */
        public NVec intersect(final NVec other){
            return NVec.of(super.intersect(other));
        }

        /**
         * 求出两个集合的差
         * @param other 另一个 NVec 对象
         * @return 集合差对象
         */
        public NVec diff(final NVec other){
            return NVec.of(super.diff(other));
        }

        /**
         * 求出两个集合的合并
         *
         * @param other 另一个 NVec 对象
         * @return 集合差对象
         */
        public NVec union(final NVec other) {
            return NVec.of(super.union(other));
        }
       
       /**
        * split 的 别名
        * 对data进行按照索引位置进行拆分<br>
        * <br>
        * @param positions 大于0的整数列表,表示切分的位点, 即切分索引位置<br>
        * 切分索引位置（区间结尾索引exclusive,所以需要的是大约0的整数） 序列,<br>
        * 对于超出过data.length则视为数组的最大长度,<br>
        * 剔除超过数组长度范围所分割的区间。<br>
        * - 比如： [0,1,2,3],按照 {2,5,6}进行切分,定义的区间为:<br>
        * [0,2),[2,5),[5,6),由于[2,5)区间跨越了 data的长度,<br>
        * 所以给它矫正为[2,3), 另外 [5,6) 区间给予剔除。<br>
        * 结果返回 [0,1],[2,3]。<br>
        * - 比如：[0,1,2,3],按照[ 2 ] 进行切分,定义了区间 [0,2),[2,4),<br>
        * 即 定义区间的时候，会自动 补填 0,和 数组常常作为分割点。<br>
        * 即对于一个长度为4的数组来说,切分简化序列 [2]相当于 [0,2,4]的 切分完整序列。
        * @return 分割片段序列集合。
        */
       public List<NVec> cuts(final Integer ...positions){
           
           return splitS(positions).collect(Collectors.toList());
       }
       
       /**
        * 对data进行按照索引位置进行拆分<br>
        * <br>
        * @param positions 大于0的整数列表,表示切分的位点, 即切分索引位置<br>
        * 切分索引位置（区间结尾索引exclusive,所以需要的是大约0的整数） 序列,<br>
        * 对于超出过data.length则视为数组的最大长度,<br>
        * 剔除超过数组长度范围所分割的区间。<br>
        * - 比如： [0,1,2,3],按照 {2,5,6}进行切分,定义的区间为:<br>
        * [0,2),[2,5),[5,6),由于[2,5)区间跨越了 data的长度,<br>
        * 所以给它矫正为[2,3), 另外 [5,6) 区间给予剔除。<br>
        * 结果返回 [0,1],[2,3]。<br>
        * - 比如：[0,1,2,3],按照[ 2 ] 进行切分,定义了区间 [0,2),[2,4),<br>
        * 即 定义区间的时候，会自动 补填 0,和 数组常常作为分割点。<br>
        * 即对于一个长度为4的数组来说,切分简化序列 [2]相当于 [0,2,4]的 切分完整序列。
        * @return 向量被cuts后所得到一个以片段选择器, (n:片段序号 从0开始)->NVec:裁剪的片段数据
        */
       public Function<Integer,NVec> cuts_picker(final Integer ...positions){
           
           final var ll = this.cuts(positions);
           
           return n->{
               final var size = ll.size();
               if(n>=size)return null;
               return ll.get(n);
           };
       }
       
       /**
        * 构造一个位于 from 与 to 之间的拷贝
        * @param from 拷贝范围的开始位置索引,从0开始, 包含inclusive
        * @param to 拷贝范围的结束位置索引, 不包含exclusive.(to 所索引可以放置于与数组范围以外)。
        * 比如：[1,2].copyOfRange(1, 3)将返回一个 [2,null]的结构
        * @return SELF 对象
        */
       public NVec copyOfRange(int from,int to) {
           return NVec.of(super.copyOfRange(from, to));
       }
       
       /**
        * 数据窗口滑动<br>
        * 对一个:1 2 3 4,按照 size:为2,step为1的参数进行滑动的结果。<br>
        * 
        * | size | 每个窗口大小为 size,每次移动的步长为step<br>
        * [1 2]<br>
        * step0:[2 3]<br>
        * - step1:[3 4]<br>
        * - - step2:[4]<br>
        * 返回:[ [1,2], [2,3], [3,4], [4] ]<br>
        *
        * @param size   滑动的窗口大小
        * @param step   每次移动的步长
        * @return 滑动窗口的列表。
        */
       public Stream<NVec> slidingS(final int size, final int step) {
       
           return this.slidingS(size, step, NVec::new);
       }
       
       /**
        * 后缀S表示是  返回的结果是 Stream类型 <br>
        * split 的 别名
        * 对data进行按照索引位置进行拆分<br>
        * <br>
        * @param positions 大于0的整数列表,表示切分的位点, 即切分索引位置<br>
        * 切分索引位置（区间结尾索引exclusive,所以需要的是大约0的整数） 序列,<br>
        * 对于超出过data.length则视为数组的最大长度,<br>
        * 剔除超过数组长度范围所分割的区间。<br>
        * - 比如： [0,1,2,3],按照 {2,5,6}进行切分,定义的区间为:<br>
        * [0,2),[2,5),[5,6),由于[2,5)区间跨越了 data的长度,<br>
        * 所以给它矫正为[2,3), 另外 [5,6) 区间给予剔除。<br>
        * 结果返回 [0,1],[2,3]。<br>
        * - 比如：[0,1,2,3],按照[ 2 ] 进行切分,定义了区间 [0,2),[2,4),<br>
        * 即 定义区间的时候，会自动 补填 0,和 数组常常作为分割点。<br>
        * 即对于一个长度为4的数组来说,切分简化序列 [2]相当于 [0,2,4]的 切分完整序列。
        * @return 分割片段的流
        */
       public Stream<NVec> splitS(final Integer ...positions){
           
           return Seq.split(data,positions).stream().map(NVec::of);
       }

       /**
        * 数据切片:按照长度进行切片
        * @param sizes 切片尺寸大小,切片尺寸会被循环使用
        * @return 切片集合
        */
       public List<NVec> slice(final int... sizes) {
       
           return super.slice(NVec::new, sizes);
       }
       
       /**
        * 后缀S表示是  返回的结果是 Stream类型 <br>
        * 数据切片:按照长度进行切片
        * @param sizes 切片尺寸大小,切片尺寸会被循环使用
        * @return 切片集合
        */
       public Stream<NVec> sliceS(final int... sizes) {
       
           return super.sliceS(NVec::new, sizes);
       }
       
       /**
        * 连接 自身与另一个 SELF结构形成一个 SELF对象
        * 例如 [1,2].concat([3,4],[5,6]) 会生成一个 [1,2,3,4,5,6]<br>
        * @param ss 另一组SELF的结构的对象数组
        * @return 新生成的self结构的对象.
        */
       public final NVec concat(final NVec ...ss) {
           return NVec.of(super.concat(ss));
       }
       
       /**
        * 对数据元素采用了过滤谓词进行过滤，生成一个过滤得出的子对象
        * @param bipredicate 过滤谓词：[id,t]->true,id 从0开始
        * @return NVec 数据对象
        */
       public NVec filter(final BiPredicate<Long,Double> bipredicate){
           
           return NVec.of(super.filter(bipredicate));
       }
       
       /**
        * 对数据元素采用了过滤谓词进行过滤，生成一个过滤得出的子对象
        * @param predicate 过滤谓词：[t]->true
        * @return NVec 数据对象
        */
       public NVec filter(final Predicate<Double> predicate){
           
           return NVec.of(super.filter(predicate));
       }
       
       /**
        * 对数据元素采用了过滤谓词进行过滤，生成一个过滤得出的子对象
        * @param filterb 过滤标记向量<br>
        * boolean类型的数过滤序列,true 返回,false 滤除，灵感来自于R的语言的下标索引<br>
        * 当filterb为null或是长度小于1时候，默认为返回所数据元素.<br>
        * filterb数据元素会被循环填充以保证可以与NVec一一对应.<br>
        * @return SELF 数据对象
        */
       public NVec filter(final Boolean ... filterb){
           
           return NVec.of(super.filter(filterb));
       }
       
       /**
        * 对数据元素采用了过滤谓词进行过滤，生成一个过滤得出的子对象
        * @param filterb 过滤标记向量<br>
        * boolean类型的数过滤序列,true 返回,false 滤除，灵感来自于R的语言的下标索引<br>
        * 当filterb为null或是长度小于1时候，默认为返回所数据元素.<br>
        * filterb数据元素会被循环填充以保证可以与NVec一一对应.<br>
        * @return SELF 数据对象
        */
       public NVec filter(final XVec<Boolean> filterb){
           
           return NVec.of(super.filter(filterb));
       }
       
       /**
        * 术语取自 haskell 的 functor <br>
        * 使用mapper转换集合data数据，变换成新的NVec
        * @param mapper 元素映射函数,dbl->dbl
        * @return U类型的数据流
        */
       public NVec fmapN(final Function<Double,Double> mapper){
           
           return new NVec(super.fmap(mapper));
       }
       
       /**
        * 术语取自 haskell 的 functor <br>
        * 使用mapper转换集合data数据，变换成新的NVec
        * @param mapper 元素映射函数,(id,dbl)->dbl, id 从0开始
        * @return U类型的数据流
        */
       public NVec fmapN(final BiFunction<Long,Double,Double> mapper){
           
           return new NVec(super.fmap(mapper));
       }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.iat(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         *
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public NVec iat(final int... indexes) {

            return NVec.of(super.iat(indexes));
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.at(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         *
         * @param <U>     nums的数值类型
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public <U extends Number> NVec at(final TVec<U, ?> indexes) {

            return NVec.of(super.at(indexes));
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.at(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         *
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public NVec at(final Number... indexes) {

            return NVec.of(super.at(indexes));
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.at(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         *
         * @param rng 索引编号范围,编号从 0开始
         * @return 包含 rng 所标定的元素所指定的NVec
         */
        public NVec at(final Range rng) {

            return NVec.of(super.at(rng.intA2()));
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         *
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public NVec igets(final int... indexes) {

            return NVec.of(super.igets(indexes));
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         *
         * @param <U>     nums的数值类型
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public <U extends Number> NVec gets(final TVec<U, ?> indexes) {

            return NVec.of(super.gets(indexes));
        }

        /**
         * 提取包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         *
         * @param indexes 索引编号序列,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public NVec gets(final Number... indexes) {

            return this.filter((id, x) -> eq(indexes).test(id, x));
        }

        /**
         * 提取不包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[1.0, 2.0, 3.0, 5.0, 7.0, 8.0, 9.0, 10.0] <br>
         *
         * @param indexes 索引编号序列,编号从 0开始
         * @return 不包含 indexes 所标定的元素所指定的NVec
         */
        public NVec gets2(final Number... indexes) {

            return this.filter((id, x) -> neq(indexes).test(id, x));
        }

        /**
         * at 和 gets 的区别就是at 对于不存在的索引会返回null,相同的索引 返回多个元素.<br>
         * 比如 [1,2,3].at(0,0,4) 会返回 [0,0,null],而 gets 则 返回 [1] <br>
         * <br>
         * 提取包含 indexes所指定的数据元素
         * 例如:<br>
         * final var xx = Range.of2(1, n).mutate(NVec::new);<br>
         * System.out.println(xx.gets(3,5)); <br>
         * 返回：[4.0, 6.0]<br>
         *
         * @param rng 索引编号序列的范围,编号从 0开始
         * @return 包含 indexes 所标定的元素所指定的NVec
         */
        public NVec gets(final Range rng) {

            return this.gets(rng.intA2());
        }

        /***
         * 生成指定大小的NVec对象 <br>
         *
         * 如果newsize大于当前数据长度 使用null进行进行补填。<br>
         *
         * @param newsize 新的尺寸大小 <br>
         * @return SELF 类型的新的对象结构
         */
        public NVec resize0(final Number newsize) {

            return NVec.of(super.resize(newsize, (Double[]) null));
        }

        /***
         * 生成指定大小的NVec对象 <br>
         *
         * 如果newsize大于当前数据长度 使用自身数据data进行循环补位进行补填。<br>
         *
         * @param newsize 新的尺寸大小 <br>
         * @return SELF 类型的新的对象结构
         */
        public NVec resize(final Number newsize) {

            return NVec.of(super.resize(newsize, this));
        }

        /***
         * 生成指定大小的NVec对象
         * @param newsize 新的尺寸大小
         * @param tt 如果newsize大于当前数据长度所使用的填充数据，数据采用循环补位进行。<br>
         * 如果 tt 为null或是长度为0，则不予进行数据填充。
         * @return SELF 类型的新的对象结构
         */
        public NVec resize(final Number newsize, NVec tt) {

            return NVec.of(super.resize(newsize, tt.data));
        }

        /***
         * 生成指定大小的NVec对象
         * @param newsize 新的尺寸大小
         * @param tt 如果newsize大于当前数据长度所使用的填充数据，数据采用循环补位进行。<br>
         * 如果 tt 为null或是长度为0，则不予进行数据填充。
         * @return SELF 类型的新的对象结构
         */
        public NVec resize(final Number newsize, Number ... tt) {

            return this.resize(newsize, NVec.of(tt));
        }


        /**
         * 头部添加
         *
         * @param tvec 待插入的数据
         * @return 插入了tvec后的新的数据向量
         */
        public NVec prepend(final TVec<Double, ?> tvec) {

            return this.insert(0, tvec);
        }

        /**
         * 尾部追加
         *
         * @param tvec 待插入的数据
         * @return 插入了tvec后的新的数据向量
         */
        public NVec append(final TVec<Double, ?> tvec) {

            return this.insert(null, tvec);
        }

        /**
         * 头部添加
         *
         * @param tt 待插入的数据
         * @return 插入了tt后的新的数据向量
         */
        public NVec prependN( final Double... tt) {

            return this.insert(0, tt);
        }

        /**
         * 尾部插入
         *
         * @param tt 待插入的数据
         * @return 插入了tt后的新的数据向量
         */
        public NVec appendN(final Double... tt) {

            return this.insert(null, tt);
        }

        /**
         * 在向量的 pos位置插入数据 nvec
         *
         * @param pos  插入的索引位置从0开始:<br>
         *             当pos为null的时候回视为this.size即在尾部进行插入<br>
         *             当pos大于当前数据长度的时候，插入位置会被自动重定位到当前向量的末尾 <br>
         *             当插入位置小于0的时候，返回 [] <br>
         * @param tvec 待插入的数据
         * @return 插入了tvec后的新的数据向量
         */
        public NVec insert(final Number pos, final TVec<Double, ?> tvec) {

            return NVec.of(super.replace(pos, pos, tvec));
        }

        /**
         * 在向量的 pos位置插入数据 tt
         *
         * @param pos 插入的索引位置从0开始:<br>
         *            当pos为null的时候回视为this.size即在尾部进行插入<br>
         *            当pos大于当前数据长度的时候，插入位置会被自动重定位到当前向量的末尾 <br>
         *            当插入位置小于0的时候，返回 [] <br>
         * @param tt  待插入的数据
         * @return 插入了tt后的新的数据向量
         */
        public NVec insert(final Number pos, Double... tt) {

            return NVec.of(super.replace(pos, pos, tt));
        }

        /**
         * 带序号的 采样点遍历更新 <br>
         * 通updator遍历访问 NVec中的每个元素。 <br>
         * 遍历的索引序号从0开始 <br>
         * <br>
         *
         * @param updator 二元回调函数 (i:索引号,dbl:采样点)->dbl,会使用  updator 的返回值更新当前的i位置的值
         * @return NVec对象本身已方便实现链式编程
         */
        public NVec update(final BiFunction<Integer, Double, Double> updator) {

            super.update(updator);
            return this;
        }

        /**
         * 使用tev的数值更新自己(不会改变数据长度）
         * @param tvec tvec中的数据会被循环使用以匹配SELF的数据长度
         * @return SELF数据对象本身  以实现链式编程
         */
        public NVec update(final TVec<Double,?> tvec) {

            return NVec.of(super.update(tvec));
        }
       
       /**
         * 使用 nvec 中的内容替换掉 start 与 end 之间的数据 <br>
         *
         * @param start 开始位置 包含 inclusive 从0开始 <br>
         *              当start小于0的时候返回[]<br>
         *              当start为null时,视为this.size()<br>
         * @param tvec 待插入的数据,当 nvec 为null时视为替换一个长度为0的数据序列
         * @return 使用 tt 中的内容替换掉 start 与 end 之间的数据 后的数据向量 （新生成）
         */
        public NVec replace(final Number start,final TVec<Double,?> tvec) {
        
            return NVec.of(super.replace(start, null, tvec));
        }

        /**
         * 使用 nvec 中的内容替换掉 start 与 end 之间的数据 <br>
         *
         * @param start 开始位置 包含 inclusive 从0开始 <br>
         * @param end   结束位置 不包含 exclusive 从0开始。end 位置需要大于start，如果小于则返回null
         *              当start小于0的时候返回[]<br>
         *              当start为null时,视为this.size()<br>
         * @param tvec  待插入的数据,当 nvec 为null时视为替换一个长度为0的数据序列
         * @return 使用 tt 中的内容替换掉 start 与 end 之间的数据 后的数据向量 （新生成）
         */
        public NVec replace(final Number start, final Number end, final TVec<Double, ?> tvec) {

            return NVec.of(super.replace(start, end, tvec));
        }
       
       /**
        * 使用 tt 中的内容替换掉 start 与 end 之间的数据 <br>
        *
        * @param start 开始位置 包含 inclusive 从0开始 <br>
        *              当start小于0的时候返回null<br>
        *              当start为null时,视为this.size()<br>
        * @param end 结束位置 不包含 exclusive 从0开始。end 位置需要大于start，如果小于则返回null
        *            如果end为null默认为start+tt.length
        * @param tt 待插入的数据,当 tt 为null时视为替换一个长度为0的数据序列
        * @return 使用 tt 中的内容替换掉 start 与 end 之间的数据 后的数据向量 （新生成）
        */
       public NVec replace(final Number start, final Number end,final Double... tt) {
           
          return NVec.of(super.replace(start, end, tt));
       }
       
       /**
        * 把start,end 之间的数据给予去除 <br>
        * start,end 需要时大于等于0的正整数，若为负数 直接  返回[] <br>
        * 当start 大于等于 当前长度的时候的，返回一个 当前SELF对象的完整复制品 <br>
        * @param start 开始位置 包含inclusive 从0开始
        * @param end 结束位置 不包含exclusive 从0开始。end 位置需要大于start，如果小于则返回null
        * @return 去除了 start 与 end 之间的数据的 SELF 对象 （新生成）
        */
       public NVec delete(final Number start, final Number end) {
           
          return NVec.of(super.delete(start, end));
       }
       
       /**
        * 删除pos位置的元素
        * 
        * @param pos 位置序号从0开始,小于向量长度
        * @return 去除掉pos位置的元素的剩余向量 （新生成）
        */
       public NVec delete(final Number pos) {

           return NVec.of(super.delete(pos));
       }
       
       /**
        * delete 函数的别名 <br>
        * 删除pos位置的元素
        * 
        * @param pos 位置序号从0开始,小于向量长度
        * @return 去除掉pos位置的元素的剩余向量 （新生成）
        */
       public NVec remove(final Number pos) {

           return this.delete(pos);
       }
       
       /**
        * 采样点遍历 <br>
        * 通cs遍历访问 TVec 中的每个 采样点。
        * @param cs 回调函数 dbl->{}
        * @return NVec对象  对象本身已方便实现链式编程
        */
       public NVec foreach(final Consumer<Double> cs) {
           
           super.foreach(cs);
           return this;
       }
       
       /**
        * 带序号的 采样点遍历 <br>
        * 通cs遍历访问 TVec中的每个 采样点。 <br>
        * 遍历的索引序号从0开始 <br>
        * <br>
        * @param cs 二元回调函数 (i:索引号,dbl:采样点)->{}
        * @return NVec对象本身已方便实现链式编程
        */
       public NVec foreach(final BiConsumer<Integer,Double> cs) {
           
          super.foreach(cs);
          return this;
       }

       
        /**
         * 数据随机权重,而后给予重排顺序
         * 
         * @return NVec 的对象实例（新生成）
         */
        public NVec shuffle() {
            return new NVec(super.shuffle());
        }

        /**
         * 数据指定权重,而后给予重排顺序
         *
         * @param weighter 排序的向量的权重函数 t->num <br>
         *                 即把 t映射成一个可以进行比较的数值权重(weight)而后按照weight进行排序：从小打到大
         * @return NVec 的对象实例（新生成）
         */
        public NVec shuffle(final Function<Double, Number> weighter) {
            return new NVec(super.shuffle(weighter));
        }

        /**
         * 数据指定权重,而后给予重排顺序
         *
         * @param mapper 元素变换器,把T 变换成一个带有权重的 U值 : <br>
         *               (i:索引序号从0开始,t:元素值) -> weightable&lt;dbl&gt;
         * @return NVec 的对象实例（新生成）
         */
        public NVec shuffle(final BiFunction<Integer, Double, Weightable<Double>> mapper) {
            return new NVec(super.shuffle(mapper));
        }

        /**
         * 数据指定权重,而后给予重排顺序
         *
         * @param weighter 权重配置器,为T指定一个权重 : (i:索引序号从0开始,t:元素值) -> num
         *                 即把 t映射成一个可以进行比较的数值权重(weight)而后按照weight进行排序：从小打到大
         * @return NVec 的对象实例（新生成）
         */
        public NVec shuffle2(final BiFunction<Integer, Double, Number> weighter) {
            return new NVec(super.shuffle2(weighter));
        }
        
        /**
         * 对元素序列进行排序
         * 
         * @return 排序后的元素向量
         */
        public NVec sorted() {
            return NVec.of(super.sorted());
        }

        /**
         * 对元素序列进行排序
         * 
         * @param comparator 元素比较函数 (a,b)-> int,a non-interfering, stateless Comparator to be used to compare stream elements
         * @return 排序后的元素向量
         */
        public NVec sorted(final Comparator<? super Double> comparator) {
            return NVec.of(super.sorted(comparator));
        }

        /**
         * 返回数据形状:依据索引序列所排成各个索引维度长度的数字列表。 <br>
         * 数据形状按照car的元素进行估计核算，注意返回的shapehi估计大小，<br>
         * 即假设XVec元素是均质的,统计类型包括:数组,XVec,Collection三类。  <br>
         * <br>
         * 这里有个有趣的问题，就是 XVec使用期子类NVec作为返回值。主要原因就是 NVec提供数值<br>
         * 计算的能力.可以方便进行维度乘积.比如 x.shape().product() 这种方式来估计 flat后<br>
         * 的空间大小的计算的便捷性.<br>
         * <br>
         * @return 当前向量的形状[第一维度,第二维度]
         */
        public NVec shapeN() {
            return this.shape(NVec::new);
        }

        /**
         * 文本格式化
         */
        public String toString() {
            
            return Arrays.toString(data);
        }

        /**
         * 取模函数 (整形除法,intdiv的别名函数) <br>
         * 整型的除法:number 被除数/divisor 除数 <br>
         * intdiv 可以用于求出一个 按照行顺序的 索引a,在按照行的长度为b进行展开后的所产生的矩阵 <br>
         * 的二维坐标.比如 对于 对于索引4,当按照b=3的周期(行长度)进行提升高纬度后他的他的二维索引就编程 <br>
         * [1,1],即 mod(4,3)的结果。<br>
         * 一种展开的索引结构示例<br>
         * [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] <br
         * [0.0, 0.0]|0.0 [0.0, 1.0]|1.0 [0.0, 2.0]|2.0 <br>
         * [1.0, 0.0]|3.0 [1.0, 1.0]|4.0 [1.0, 2.0]|5.0 <br>
         * [2.0, 0.0]|6.0 [2.0, 1.0]|7.0 [2.0, 2.0]|8.0 <br>
         *
         * @param number 被除数
         * @param divisor 除数
         * @return 第0位:商,第一位:余数,即 [0:商,1:余数]
         */
        public static NVec mod(final Number number, final Number divisor){
            return intdiv(number,divisor);
        }

        /**
         * 整型的除法:number 被除数/divisor 除数 <br>
         * intdiv 可以用于求出一个 按照行顺序的 索引a,在按照行的长度为b进行展开后的所产生的矩阵 <br>
         * 的二维坐标.比如 对于 对于索引4,当按照b=3的周期(行长度)进行提升高纬度后他的他的二维索引就编程 <br>
         * [1,1],即 intdiv(4,3)的结果。<br>
         * 一种展开的索引结构示例<br>
         * [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] <br
         * [0.0, 0.0]|0.0 [0.0, 1.0]|1.0 [0.0, 2.0]|2.0 <br>
         * [1.0, 0.0]|3.0 [1.0, 1.0]|4.0 [1.0, 2.0]|5.0 <br>
         * [2.0, 0.0]|6.0 [2.0, 1.0]|7.0 [2.0, 2.0]|8.0 <br>
         * 
         * @param number 被除数
         * @param divisor 除数
         * @return 第0位:商,第一位:余数,即 [0:商,1:余数]
         */
        public static NVec intdiv(final Number number, final Number divisor) {
            
            return NVec.of(new int[] { number.intValue() / divisor.intValue(), number.intValue() % divisor.intValue() });
        }
        
        /**
         * mode function (取模函数) <br>
         * 整型的除法:x 被除数/mode 除数 <br>
         * modeOf 可以用于求出一个 按照行顺序的 索引a,在按照行的长度为b进行展开后的所产生的矩阵 <br>
         * 的二维坐标.比如 对于 对于索引4,当按照b=3的周期(行长度，模mode)进行提升高纬度后他的他的二维索引就编程 <br>
         * [1,1],即 modeOf(3).apply(4)的结果。<br>
         * 一种展开的索引结构示例<br>
         * [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] <br>
         * [0.0, 0.0]|0.0 [0.0, 1.0]|1.0 [0.0, 2.0]|2.0 <br>
         * [1.0, 0.0]|3.0 [1.0, 1.0]|4.0 [1.0, 2.0]|5.0 <br>
         * [2.0, 0.0]|6.0 [2.0, 1.0]|7.0 [2.0, 2.0]|8.0 <br>
         * 
         * @param mode 除数
         * @return x->[第0位 商,第一位余数]
         */
        public static Function<Integer,NVec> modeOf(final Number mode) {
            
            return x->intdiv(x,mode);
        }
        
        /**
         * mode function (取模函数)并分量提取 <br>
         * 整型的除法:x 被除数/mode 除数 <br>
         * modeOf 可以用于求出一个 按照行顺序的 索引a,在按照行的长度为b进行展开后的所产生的矩阵 <br>
         * 的二维坐标.比如 对于 对于索引4,当按照b=3的周期(行长度，模mode)进行提升高纬度后他的他的二维索引就编程 <br>
         * modeOf(3,1).apply(4) 就是提取4/3的结果[1,1*]的第2个元素,即1<br>
         * 一种展开的索引结构示例<br>
         * [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] <br>
         * [0.0, 0.0]|0.0 [0.0, 1.0]|1.0 [0.0, 2.0]|2.0 <br>
         * [1.0, 0.0]|3.0 [1.0, 1.0]|4.0 [1.0, 2.0]|5.0 <br>
         * [2.0, 0.0]|6.0 [2.0, 1.0]|7.0 [2.0, 2.0]|8.0 <br>
         * 
         * @param mode 除数
         * @param idx 提取的分量[0或1],除此之外，越界异常
         * @return x->[第0位 商,第一位余数]在idx位置的值
         */
        public static Function<Integer,Integer> modeOf(final Number mode,int idx) {
            
            return x->intdiv(x,mode).get(idx).intValue();
        }

        /**
         * 构造一个NVec对象，用于专门lambda构造,不能有重载
         *
         * @param data 向量的数据元素序列
         * @return NVec 实例以便实现链式编程
         */
        public static NVec cons(final Object... data) {

            return NVec.of(Arrays.stream(data).map(PatternCase.<Object, Number>nullcase(0d)
                    .typeof(Number.class, Number::doubleValue)
                    .typeof(String.class, line -> {
                        final var matcher = Pattern.compile("([+-]?\\d+(\\.\\d+)*)").matcher(line);
                        return matcher.find() ? Double.parseDouble(matcher.group()) : 0d;
                    })
                    .typeof(LocalDateTime.class, ldt -> ldt.get(ChronoField.HOUR_OF_DAY))
                    .typeof(LocalDate.class, ld -> ld.get(ChronoField.DAY_OF_MONTH))
                    .typeof(LocalTime.class, lt -> lt.get(ChronoField.HOUR_OF_DAY))
                    .typeof(Date.class, Date::getTime).fn()
            ).toArray(Number[]::new));
        }

        /**
         * 构造一个NVec对象
         * @param rng 区间范围
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final Range rng) {
            
            return new NVec(rng);
        }

        /**
         * 构造一个NVec对象
         * @param nvec 拷贝一个 nvec
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final NVec nvec) {
            
            return new NVec(nvec.toArray());
        }
        
        /**
         * 构造一个NVec对象
         * @param nvecs NVec 对象的集合
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final NVec ...nvecs) {

            //noinspection OptionalGetWithoutIsPresent
            return Stream.of(nvecs).reduce(NVec::concat).get();
        }
        
        /**
         * 构造一个NVec对象(拷贝XVec)
         * @param xvec vec对象。
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final XVec<? extends Number> xvec) {
            
            return new NVec(xvec);
        }
        
        /**
         * 构造一个NVec对象
         * @param stream 一段数字构造成的流(需要是有限流,否则会造成读取灾难)
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final Stream<? extends Number> stream) {
            
            return new NVec(XVec.OF(stream));
        }

        /**
         * 构造一个NVec对象
         * @param data 向量的数据元素序列
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final Number ... data) {

            return new NVec(data);
        }
        
        /**
         * 构造一个NVec对象
         * @param data 向量的数据元素序列
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final Double ... data) {
            
            return new NVec(data);
        }
        
        /**
         * 构造一个NVec对象
         * @param ll 列表类型的数据
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final List<? extends Number> ll) {
            final var aa = ll.toArray(Number[]::new);
            return new NVec(aa);
        }

        /**
         * 构造一个NVec对象
         * @param data 向量的数据元素序列
         * @return NVec 实例以便实现链式编程
         */
        public static NVec of(final int [] data) {
            
            return new NVec(data);
        }
        
        /**
        * 构造一个向量对象，带有索引序号生成器 <br>
        * @param n 向量长度，大于等于1的正整数
        * @param generator 向量元素的生成器:int索引序号->T, 索引序号从0开始
        * @return NVec
        */
       public static NVec of(int n,Function<Integer,Number> generator) {
           
           return NVec.of(XVec.OF(n, generator));
       }
        
        /**
         * 生成一个 双精度(Double[][] 类型)二维矩阵 (主顺序为行序的 矩阵  即 行序矩阵)<br>
         * 
         * 数组 的 第一索引顺序 与  stream 的元素序列顺序相同 <br>
         * 数组 的 第而索引顺序 与  NVec 的元素序列顺序相同 <br> 
         * 即 返回的矩阵的 维度为 :  n x size <br>
         * n 是 stream 长度,size 是  NVec 的长度 <br> 
         * 
         * @param stream NVec的流
         * @return 双精度二维矩阵 。矩阵的 维度 n x size
         */
        public static Double[][] toArray2( final Stream<NVec> stream){
            
            return stream.map(e->e.data).toArray(Double[][]::new);
        }
        
        /**
         * 生成一个 双精度(Double[][] 类型)二维矩阵 (主顺序为行序的 矩阵  即 行序矩阵)<br>
         * 
         * 数组 的 第一索引顺序 与  stream 的元素序列顺序相同 <br>
         * 数组 的 第而索引顺序 与  NVec 的元素序列顺序相同 <br> 
         * 即 返回的矩阵的 维度为 :  n x size <br>
         * n 是 stream 长度,size 是  NVec 的长度 <br> 
         * 
         * @param <U> 结果类型
         * @param stream NVec的流
         * @param mapper 数组变换函数
         * @return 双精度二维矩阵 。矩阵的 维度 n x size
         */
        public static <U> U toArray2(final Stream<NVec> stream, final Function<Double[][], U> mapper) {
            
            return mapper.apply(NVec.toArray2(stream));
        }

        /**
         * 生成一个 双精度二维矩阵 (主顺序为行序的 矩阵 即 行序矩阵 )<br>
         * 
         * 数组 的 第一索引顺序 与  stream 的元素序列顺序相同 <br>
         * 数组 的 第而索引顺序 与  NVec 的元素序列顺序相同 <br> 
         * 即 返回的矩阵的 维度为 :  n x size <br>
         * n 是 stream 长度,size 是  NVec 的长度 <br> 
         * 
         * @param stream NVec的流
         * @return 双精度二维矩阵 。矩阵的 维度 n x size
         */
        public static double[][] toArray( final Stream<NVec> stream){
            
            return stream.map(NVec::dbls).toArray(double[][]::new);
        }

        /**
         * 生成一个 双精度(Double[][] 类型)二维矩阵 (主顺序为行序的 矩阵  即 行序矩阵)<br>
         * 
         * 数组 的 第一索引顺序 与  stream 的元素序列顺序相同 <br>
         * 数组 的 第而索引顺序 与  NVec 的元素序列顺序相同 <br> 
         * 即 返回的矩阵的 维度为 :  n x size <br>
         * n 是 stream 长度,size 是  NVec 的长度 <br> 
         * 
         * @param <U> 结果类型
         * @param stream NVec的流
         * @param mapper 数组变换函数
         * @return 双精度二维矩阵 。矩阵的 维度 n x size
         */
        public static <U> U toArray(final Stream<NVec> stream, final Function<double[][], U> mapper) {
            
            return mapper.apply(NVec.toArray(stream));
        }

        /**
         * xvec归集器
         *
         * @param <T> 源数据类型
         * @param mapper 类型变换器 dbl->dbl
         * @return 把T类型的流归结成XVec&lt;U&gt; 类型的归集器
         */
        public static <T> Collector<T, ?, NVec> nveclc(final Function<T, Number> mapper) {
            return Collector.of(ArrayList::new, (List<Double> aa, T t) -> aa.add(mapper.apply(t).doubleValue()), (aa, bb) -> {
                aa.addAll(bb);
                return aa;
            }, NVec::of);
        }

        /**
         * xvec归集器
         *
         * @return 把T类型的流归结成XVec&lt;T&gt; 类型的归集器
         */
        public static Collector<? super Number, ?, NVec> nveclc() {
            return nveclc(e -> e);
        }
        
    }// NVec
    
    /**
     * 插值运算<br>
     * 连续性线条的填充算法算法：<br>
     * [int]->[int]<br>
     * <br>
     * 连续算法为状态算法不能够在多个流中进行共享使用<br>
     * 即 不可以:
     * final smooth = nvec_continuous_line2();<br>
     * stream1.flatMap(smooth);<br>
     * stream2.flatMap(smooth);<br>
     * 只能够:<br>
     * stream.flatMap(nvec_continuous_line2()); <br>
     * <br>
     * 根据前一个节点的y值构造连续线条 <br>
     * @return 连续性线条绘制方法
     */
    public static Function<int[],Stream<int[]>> continuous_line(){
        
        return continuous_line(false);
    }
    
    /**
     * 插值运算<br>
     * 连续性线条的填充算法算法：<br>
     * nvec->[int] <br>
     * <br>
     * 连续算法为状态算法不能够在多个流中进行共享使用<br>
     * 即 不可以:<br>
     * final smooth = nvec_continuous_line();<br>
     * stream1.flatMap(smooth);<br>
     * stream2.flatMap(smooth);<br>
     * 只能够:<br>
     * stream.flatMap(nvec_continuous_line2()); <br>
     * <br>
     * 根据前一个节点的y值构造连续线条 <br>
     * @return 连续性线条绘制方法
     */
    public static Function<NVec,Stream<int[]>> nvec_continuous_line(){
        
        final var f = continuous_line(false);
        return nvec->f.apply(nvec.ints());
    }
    
    /**
     * 插值运算<br>
     * 连续性线条的填充算法算法：<br>
     * nvec->nvec <br>
     * <br>
     * 连续算法为状态算法不能够在多个流中进行共享使用<br>
     * 即 不可以:<br>
     * final smooth = nvec_continuous_line2();<br>
     * stream1.flatMap(smooth);<br>
     * stream2.flatMap(smooth);<br>
     * 只能够:<br>
     * stream.flatMap(nvec_continuous_line2()); <br>
     * <br>
     * 根据前一个节点的y值构造连续线条 <br>
     * @return 连续性线条绘制方法
     */
    public static Function<NVec,Stream<NVec>> nvec_continuous_line2(){
        final var f = continuous_line(false);
        return nvec->f.apply(nvec.ints()).map(NVec::new);
    }
    
    /**
     * 插值运算<br>
     * 连续性线条的填充算法算法：<br>
     * 根据前一个节点的y值构造连续线条 <br>
     * <br>
     * 连续算法为状态算法不能够在多个流中进行共享使用<br>
     * 即 不可以:<br>
     * final smooth = continuous_line(true);<br>
     * stream1.flatMap(smooth);<br>
     * stream2.flatMap(smooth);<br>
     * 只能够:<br>
     * stream.flatMap(nvec_continuous_line2()); <br>
     * <br>
     * @param prevY_exclusive prev在是否在连续性补充中给予排除,true 不从prev开始,false从prev开始<br>
     * 实验证明从prev[1]包含绘制 要比 不包含绘制要好。在绘制正余弦曲线的时候 prev[1] 不包含<br>
     * 会造成断连现象。建议设置成 false，表示包含prev,从前一点高度位置上多补一个像素。以增加连续性
     * @return 连续性线条绘制方法
     */
    public static Function<int[],Stream<int[]>> continuous_line(boolean prevY_exclusive){
        
        final var arX = new AtomicReference<int[]>();// 前一个点状态缓存
        final var arY = new AtomicReference<int[]>(); // 前一个点状态缓存
        final var MAX_SIZE = 300; // 最大的填充跨度
        
        return eX -> { // 填充点e 表示 像素点的颜色向量[x,y,r,g,b], 0#x,1#y,表示像素点e的坐标,后续为rgb颜色值
            final var prevX = arX.getAndSet(eX); // 前一个节点
            
            if (prevX != null && Math.abs(prevX[1] - eX[1]) > MAX_SIZE) { // 超过X最大间距
                arX.set(null);
                return Stream.of(eX); // 第一个数据点;
            } else if(prevX!=null) {// 尝试在X轴的方向进行填充
                final var x0 = prevX[0]; // 上一个节点的X坐标
                final var x1 = eX[0]; // 当前节点的X坐标
                final var lastX = Arrays.copyOf(prevX, prevX.length); // 复制上一个节点,是临时用的节点
                final var ratioX = (eX[1] - prevX[1]) * 1d / (eX[0] - prevX[0]);// y 增长率
                final var xs = Range.of2(x0, x1).intStream().limit(MAX_SIZE).map(i -> {// 最多补填 100个元素
                    lastX[0] = i; // 上一个节点的 横坐标
                    lastX[1] = prevX[1] + (int) ((i - x0) * ratioX); // 上一个节点的 纵坐标
                    return Arrays.copyOf(lastX, prevX.length); // 返回新创建的节点
                }); // xs:Stream<int[]>，对x方向进行连续化
                
                // 对 _xs 进行调整防止 出现 相同的 x不同的y,[x0,y0;x0,y1;...,x0,yn]即垂直线状态下的y值缺失的情况。
                final var _xs = ((lastX[1]==eX[1]) ? xs : Stream.concat(xs, Stream.of(eX))); // 调整后的xs序列
                final var ys = _xs.flatMap(eY -> { // 针对X尝试在Y方向进行填充,此时的xs已经是连续化了。
                    final var prevY = arY.getAndSet(eY); // 获取前一个元素的Y值
                    if (prevY == null) {
                        return Stream.of(eY);
                    } else if (Math.abs(prevY[1] - eY[1]) > MAX_SIZE) { // 超过Y方向最大间距
                        arY.set(null);
                        return Stream.of(eY); // 第一个数据点;
                    } else { // 由于已经通过 连续化生成了xs,所以Y就不用计算拟合增长量上的估计了
                        // 实验证明从prevY[1]包含绘制 要比 不包含绘制要好,对于正余弦曲线的经验 prevY[1] 不包含,会造成断连现象。
                        return (prevY_exclusive // prevY是否包含
                            ? Range.of12(prevY[1], eY[1]) // prev[1] 不包含
                            : Range.of2(prevY[1], eY[1]) // prev[1] 包含
                        ).mapInt(i -> NVec.of(eY).idval_set(1, i).ints()); // 从第二个点开始做连续性填充
                    } // if
                }); // ys
                
                return ys;
            } else { // prevX == null
                return Stream.of(eX);
            }// if prevX
        }; // eX
    }

    /**
     * 矩阵化一个向量 <br>
     * 一个index2value列表 等价于一个矩阵。
     * 
     * @param <T> 向量的元素类型
     * @param <U> 矩阵的元素类型
     * @param vectors 数据向量
     * @param indexer 行号 列号 t->{行索引,列索引}
     * @param valueer 值提取 t->u 
     * @return U[][] 结果矩阵
     */
    @SuppressWarnings("unchecked")
    public static <T,U> U[][] matrix (
        final List<T> vectors,
        final Function<T,int[]> indexer,
        final Function<T,U> valueer ){
        
        final int[] aa = {0,0};// 临时数据空间，用来统计第一维度，第二维度的最大数据。以方便生成结果矩阵的宽度和高度。
        final var idxvalues = DataPoint.analyze ( vectors, indexer, valueer, DataPoint::new,
            ivp->{// 中间结果处理
                final var index = ivp.index(); // 提取索引值
                if(aa[0]<index[0]) aa[0] = index[0];
                if(aa[1]<index[1]) aa[1] = index[1];
        }).collect(Collectors.toList()); // 注意一定要启动Collectors做列表化操作，以完成实际的数据搜集工作，否则aa不会做更新。
        final Class<U> clazz = DataPoint.sndclass(idxvalues).orElse((Class<U>)Object.class);
        final int width = aa[0]+1;// 矩阵宽度
        final int height = aa[1]+1; // 高度
        final var uu = (U[][])Array.newInstance(clazz, width,height); // 结果的二维矩阵数组
        
        // 索引值数据 ivps 填充到目标结构数组之中
        for( final DataPoint<U> idxval: idxvalues ) idxval.assignTo(uu);
        
        return uu;// 返回二维矩阵数组。
    }

    /**
     * 直线绘制算法<br>
     * bresenham_line 的算法特点就是 只有 整数运算，没有 浮点运算，这就是它的高妙的地方。<br>
     * @param x0 开始点  x
     * @param y0 开始点  y
     * @param x1 终止点  x
     * @param y1 终止点  y
     * @param setPixel 点绘制函数
     */
    public static void bresenham_line(
        final int x0, int y0, 
        final int x1, final int y1, 
        final BiConsumer<Integer, Integer> setPixel) {
        
        int dx = x1 - x0; // x 方向的延展跨度
        int dy = y1 - y0; // y 方向的延展跨度
        int ux = dx > 0 ? 1 : -1;// x的增量单位，取1或-1
        int uy = dy > 0 ? 1 : -1;// y的增量单位，取1或-1
        int x = x0; // 当前节点的横坐标
        int y = y0; // 当前节点的纵坐标
        int eps = 0; // eps为累加误差
        
        dx = Math.abs(dx);
        dy = Math.abs(dy);
        
        if (dx > dy) { // 按  x 轴向 进行展开,简单的说就是 就是提取延展跨度最大的方向做为主方向。
            for (x = x0; x != x1; x += ux) {
                setPixel.accept(x, y);
                eps += dy;
                if ((eps << 1) >= dx) {
                    y += uy;
                    eps -= dx;
                }// if
            }// for
        } else { // 按  y 轴向 进行展开
            for (y = y0; y != y1; y += uy) {
                setPixel.accept(x, y);
                eps += dx;
                if ((eps << 1) >= dy) {
                    x += ux;
                    eps -= dy;
                }// if
            }// for
        } // if
    }
    
    /**
     * 生成一个5*5的[R,I] 旋转矩阵(左乘结构)    <br>
     * R 是一个2x2维的旋转子矩阵:<br>
     * cos(theta)    -sin(theta)        <br>
     * sin(theta)    cos(theta)        <br>
     * I 是一个3x3维的单位矩阵。             <br>
     * @param theta 旋转角度(正方向为逆时针方向)
     * @return 旋转矩阵[R,I]
     */
    public static DataMatrix<Double> rotateMx(final double theta) {
        
        return rotateMx(theta,e->e);
    }
    
    /**
     * 生成一个5*5的[R,I] 旋转矩阵(左乘结构)    <br>
     * R 是一个2x2维的旋转子矩阵:<br>
     * cos(theta)    -sin(theta)        <br>
     * sin(theta)    cos(theta)        <br>
     * I 是一个3x3维的单位矩阵。             <br>
     * @param <T> 返回值的类型即mapper的结果类型
     * @param theta 旋转角度(正方向为逆时针方向)
     * @param mapper 矩阵变换器 : mx 5*5矩阵 -> t
     * @return 旋转矩阵[R,I]
     */
    public static <T> T rotateMx(final double theta, final Function<DataMatrix<Double>,T> mapper) {
        
        final var mx = NVec.of( // 旋转矩阵
            //列向量的变换分块矩阵:坐标旋转
            cos(theta), -sin(theta),     0d,0d,0d,
            sin(theta), cos(theta),      0d,0d,0d,
            // 列向量的保留分块矩阵:颜色数据矩阵
            0d,         0d,              1d,0d,0d,
            0d,         0d,              0d,1d,0d,
            0d,         0d,              0d,0d,1d
        ).reshape2mx(5, 5);// 随机生成一个矩阵
        
        return mapper.apply(mx);
    }
    
    /**
     * 生成一个 xyZero列向量 矩阵。<br>
     * 向量内容为:[[x],[y],[0d],[0d],[0d]]
     * @param x 第一元素
     * @param y 第二元素
     * @return xyZero列向量,[[x],[y],[0d],[0d],[0d]]
     */
    public static DataMatrix<Double> xyZero(final Number x,Number y ) {
        
        return xyZero(x,y,e->e);
    }
    
    /**
     * 生成一个 xyZero列向量 矩阵。<br>
     * 向量内容为:[[x],[y],[0d],[0d],[0d]]
     * @param <T> 返回值的类型即mapper的结果类型
     * @param x 第一元素
     * @param y 第二元素
     * @param mapper 矩阵变换器：mx 5*1 列向量矩阵 -> t
     * @return xyZero列向量,[[x],[y],[0d],[0d],[0d]]
     */
    public static <T> T xyZero(final Number x, final Number y, final Function<DataMatrix<Double>,T> mapper ) {
        
        final var mx = NVec.of(x.doubleValue(),y.doubleValue(),0d,0d,0d).reshape2mx(5, 1);
        
        return mapper.apply(mx);
    }
    
    /**
     * 生成一个2pi周期间隔的采样点 <br>
     * 生成逻辑为 :Range.of2(-PI, PI,2*PI/n.intValue()) <br>
     * 
     * @param n : 采样点数量-1
     * @return Range 区间范围 采样点序列 控制结构。
     */
    public static Range range2pi(final Number n) {
        
        return Range.of2(-PI, PI,2*PI/n.intValue()); // 一个周期的采样点区间
    }
    
    /**
     * 生成一个 旋转变换函数
     * @param theta 旋转角度(正方向为逆时针方向)
     * @return 旋转变换函数
     */
    public static Function<DataMatrix<Double>,DataMatrix<Double>> rotate(final double theta) {
        
        return mx->rotateMx(theta).mmult(mx);
    }
    
    /**
     * 等于(长整形比较）
     * 
     * @param <ID> 编号类型
     * @param <T>  元素类型
     * @param nums 序号序列
     * @return 等于过滤器 （id,t)->boolean
     */
    public static <T, ID extends Number> BiPredicate<ID, T> eq(final Number... nums) {

        return (id, n) -> {
            for (Number num : nums)
                if (num.longValue() == id.longValue())
                    return true;
            return false;
        };
    }

    /**
     * 不等于(长整形比较）
     * 
     * @param <ID> 编号类型
     * @param <T>  元素类型
     * @param nums 序号序列
     * @return 不等于过滤器 （id,t)->boolean
     */
    public static <T, ID extends Number> BiPredicate<ID, T> neq(final Number... nums) {

        return (id, n) -> !eq(nums).test(id, n);
    }

    /**
     * 这是模仿MATLAB的meshgrid生成网格采样点的函数。
     * 
     * @param nums 维度序列的尺寸大小,默认为采用rG(0,num)来进行各个轴向的维度范围进行构造
     * @return 网格采样点
     */
    public static Stream<NVec> meshgrid(final Number... nums) {

        return meshgrid(Arrays.stream(nums).map(Number::intValue).map(e -> Range.rG(0, e)).toArray(Range[]::new));
    }

    /**
     * 这是模仿MATLAB的meshgrid生成网格采样点的函数。
     * 
     * @param rngs 各个轴向的维度范围序列。
     * @return 网格采样点
     */
    public static Stream<NVec> meshgrid(final Range... rngs) {

        return Range.cph(rngs);
    }
    
    /**
     * 这是模仿MATLAB的meshgrid生成网格采样点的函数。
     * 
     * @param nums 维度序列的尺寸大小,默认为采用rG(0,num)来进行各个轴向的维度范围进行构造
     * @return 网格采样点
     */
    public static Stream<Double[]> dbl_meshgrid(final Number... nums) {
        return meshgrid(nums).map(NVec::data);
    }
    
    /**
     * 这是模仿MATLAB的meshgrid生成网格采样点的函数。
     * 
     * @param nums 维度序列的尺寸大小,默认为采用rG(0,num)来进行各个轴向的维度范围进行构造
     * @return 网格采样点
     */
    public static Stream<Integer[]> int_meshgrid(final Number... nums) {
        return meshgrid(nums).map(NVec::intA);
    }
    
    /**
     * 这是模仿MATLAB的meshgrid生成网格采样点的函数。
     * 
     * @param nums 维度序列的尺寸大小,默认为采用rG(0,num)来进行各个轴向的维度范围进行构造
     * @return 网格采样点
     */
    public static Stream<Long[]> lng_meshgrid(final Number... nums) {
        return meshgrid(nums).map(NVec::lngA);
    }
    
    /**
     * 这是模仿MATLAB的meshgrid生成网格采样点的函数。
     * 
     * @param nums 维度序列的尺寸大小,默认为采用rg(0,num)来进行各个轴向的维度范围进行构造
     * @return 网格采样点
     */
    public static Stream<Double[]> dbl_meshgrid2(final Number... nums) {
        for(int i=0;i<nums.length;i++)nums[i] = nums[i].intValue()-1;
        return meshgrid(nums).map(NVec::data);
    }
    
    /**
     * 这是模仿MATLAB的meshgrid生成网格采样点的函数。
     * 
     * @param nums 维度序列的尺寸大小,默认为采用rg(0,num)来进行各个轴向的维度范围进行构造
     * @return 网格采样点
     */
    public static Stream<Integer[]> int_meshgrid2(final Number... nums) {
        for(int i=0;i<nums.length;i++)nums[i] = nums[i].intValue()-1;
        return meshgrid(nums).map(NVec::intA);
    }
    
    /**
     * 这是模仿MATLAB的meshgrid生成网格采样点的函数。
     * 
     * @param nums 维度序列的尺寸大小,默认为采用rg(0,num)来进行各个轴向的维度范围进行构造
     * @return 网格采样点
     */
    public static Stream<Long[]> lng_meshgrid2(final Number... nums) {
        for(int i=0;i<nums.length;i++)nums[i] = nums[i].intValue()-1;
        return meshgrid(nums).map(NVec::lngA);
    }

    /**
     * NVec结构的颜色
     * @param color rgb的字符串颜色,比如:"#ff0000"表示红色
     * @return NVec 的rgb结构颜色
     */
    public static NVec rgbNVec(final String color) {
        
        return NVec.of(ImageOps.rgb(color));
    }
    
    /**
     * 别名函数，为T构造一个别名环境
     * @param <T> T类型的变量
     * @param <U> U类型的变量
     * @param t T类型的变量
     * @param op 操作函数
     * @return U 类型的结果
     */
    public static <T,U> U withT(final T t, final Function<T,U> op){
        
        return op.apply(t);
    }
    
    /**
     * 别名函数，为T构造一个别名环境
     * @param <T> T类型的变量
     * @param <U> U类型额变量
     * @param <V> 返回的结果值
     * @param t T类型的变量
     * @param u U类型额变量
     * @param op 操作函数
     * @return V类型的结果
     */
    public static <T,U,V> V withTU(final T t, final U u, final BiFunction<T,U,V> op){
        
        return op.apply(t,u);
    }
    
    /**
     * 简单的打印输出函数(不自带有换行)
     * @param objs 打印输入的数据，数据值之间采用"\t"分隔符 进行分隔
     * @return 打印输出的数内容
     */
    public static String print(final Object ... objs) {
        
        final var line = Arrays.stream(objs).map(e->{
            if(e instanceof Object[][]){ // 二维数组
                final var oo = (Object[][])e;
                return Arrays.stream(oo).map(Arrays::deepToString).collect(Collectors.joining("\n"));
            }if(e instanceof Object[]){ // 一维数组
                return Arrays.deepToString((Object[])e);
            }else{ // 其他数据
                return e+"";
            }
        }).collect(Collectors.joining("\t"))
        .replaceAll("\n\\s+", "\n"); // 把换行符之后的空格给取消掉,即顶格显示
        
        System.out.print(line);
        return line;
    }

    /**
     * 简单的打印输出函数(自带有换行)
     * 
     * @param objs 打印输入的数据，数据值之间采用"\t"分隔符 进行分隔
     * @return 打印输出的数内容
     */
    @SafeVarargs
    public static <T> String println(final T... objs) {

        final var line = print(objs);
        System.out.println();
        return line;
    }
    
    /**
     * 绘制区间:<br>
     * 主区间范围 Range[自变量定义域] <br>
     * 自变量(x或者y)在延展方向上的 取值范围。即 定义域，这是一个半闭半开空间,[start,end)
     */
    private Range range; 
    
    /**
     *  绘图画布的默认画笔色Color
     */
    private int[] color = RED; 
    
    /**
     * 是否 x,y被翻转<br>
     * 
     * true:第一索引y,第二索引x 即 颜色点向量 [y,x,r,g,b] <br>
     * false:第一索引x,第二索引y 即 颜色点向量 [x,y,r,g,b] <br>
     */
    private boolean flipFlag = false;
    
    /**
     * 回退 stack <br>
     * 保存状态过程信息 如 默认绘图色 Color,主区间范围 Range[自变量定义域] 等 的设置 已便于处理  必要的 回退请求 的数据结构
     */
    private final MultipleStack globalStack = new MultipleStack();
    
    public static final int[] RED = new int[] {255,0,0}; // 红色
    public static final int[] GREEN = new int[] {0,255,0}; // 绿色
    public static final int[] YELLOW = new int[] {255,255,0}; // 黄色
    public static final int[] BLUE = new int[] {0,0,255}; // 蓝色
    public static final int[] MAGENTA = new int[] {255,0,255}; // 洋红色
    public static final int[] CYAN = new int[] {0,255,255}; // 青色
    public static final int[] BLACK = new int[] {0,0,0}; // 褐色
    public static final int[] WHITE = new int[] {255,255,255}; // 白色
    
    public static boolean debug = false; // 调试标记
}